perl -pe 'g/^[1-777])/g' data.txt 

where I try to all numbers at the beginning of a line with ")" following them etc 1), 67) and 777).

Data where all question numbers should (etc 1), 16), 68) ... but not 16. and not 778)) be found

1) hello 
A) Options here which should be not matched. 
16) hello 16. old
A) Options here which should be not matched. 
68) yes question
A) Options here which should be not matched. 
582) hurray
A) Options here which should be not matched. 
A) Options here which should be not matched. 

where find only numbers until 777.

Wanted output


which I can then feed to my Sed command. Lastly if possible, return the result as comma-separated for this command: sed -n '1,4,582' full_data.txt, discussed here, so some sort of piping from perl to sed or just in perl?

How can you return all numbers at the beginning of the line?

  • 1
    To me the question is incomprehesible. - Why get "1, 4, 582" for "1, 67, 582" ? - What are the input data, what are the selectors, and what are the exact expected results for the sample input selectors and sample data? - Please provide consistent data. - In what form are the selectors provided; hardcoded?
    – Janis
    Jun 15 '15 at 12:07
  • @Janis I want to find all characters which has ) after them. The data is just a dummy example. There can be many other numbers too. Jun 15 '15 at 12:14
  • 1
    Is the 777 a limit, so 778) should be ignored? Also, why should 777) not be found in the abovementioned example? Please specify by editing your question.
    – Ned64
    Jun 15 '15 at 12:21
  • @Ned64 Sorry my mistake. Fixed! Jun 15 '15 at 12:24
  • 1
    @Masi Did you want the numbers only, at the end? Please give example overall output, then I can adjust my answer below to include this post-formatting.
    – Ned64
    Jun 15 '15 at 12:41

As some clarification iterations showed, only integer numbers and with values not larger than 777 shall be collected into a comma separated list. Here we go:

awk -F ')' '$1~/^[0-9]+$/ && $1<=777 {print $1}' <datafile | paste -sd,

Note: To match an integer range you can in awk also write:

awk -F ')' '$1>=1 && $1<=777 {print $1}' <datafile | paste -sd,

I keep the variants below as building blocks for related tasks.

To create all question numbers:

cut -d ')' -f1 <datafile | paste -sd,

which creates this output:


Or, if entries with empty answers (like 777) shall not be considered:

awk -F ') ?' '$2!="" {print $1}' <datafile | paste -sd,

Or, if there's a numerical limit of 777 to consider:

awk -F ')' '$1<=777 {print $1}' <datafile | paste -sd,

Or to match only integer numbers in the first field:

awk -F ')' '$1~/^[0-9]+$/ {print $1}' <datafile | paste -sd,
  • This command cut -d ')' -f1 <data2.txt returns also text after the number. Jun 15 '15 at 12:27
  • @Masi; It should not, and certainly does not in my tests. - Note -d specifies the delimiter, and -f1 prints only the first field, i.e. the number before the delimiter.
    – Janis
    Jun 15 '15 at 12:29
  • All numbers are at the beginning of the line. So I think it is better to match cases at the beginning of lines with number [1-777] and (. Jun 15 '15 at 12:29
  • 1
    Inspect carefully your files (have you used the correct data file?) and the commands you typed (have you typed it correctly?). Verify that the ) in your data file is the same as the one you put on command line. Finally try calling export LANG=C and export LC_ALL=C before you issue the commands.
    – Janis
    Jun 15 '15 at 12:44
  • 1
    @Masi; the trick is that with a field separator defined as ) you only have to compare the first field $1 to be sure it's at the beginning. All solutions above consider the first field. - If you are now asking about line without ) then you cannot use that field separator. You can match lines starting with digits like this: /^[0-9]/. But to match, extract and print them in awk you'll have to do, e.g.: awk 'match($0,/^[0-9]+/) {print substr($0,RSTART,RLENGTH)}'.
    – Janis
    Jun 15 '15 at 15:43

I would first extract candidates, then check for the maximum 777 later:

egrep '^[0-7]?[0-9][0-9]?)' file | sed 's/^\([0-7]\?[0-9][0-9]\?\))/\1 )/' | awk '($1 < 778) {print $0}' | sed 's/^\([0-7]\?[0-9][0-9]\?\) ).*/\1,/' | tr --delete \\n | sed 's/,$/\n/'

It works for my test files. (EDIT1: The last sed now gives the number only EDIT 2: removed trailing ,)

  • Your command also returns everything after the number. It should return only the numbers separated by commas like 1,2,3,.... Sorry, I found the bug and provided complete data in the body. Jun 15 '15 at 12:44
  • I was not sure before. Changed that now!
    – Ned64
    Jun 15 '15 at 12:49
  • I get this as an output 1) hello 16) hello 16. old 68) yes question 582) hurray before tr -part. Jun 15 '15 at 12:50
  • Are you sure you have used the .* part in the sed? All text should be deleted (and is in my test data): echo '21) 34)'\\n'23)f' | egrep '^[0-7]?[0-9][0-9]?)' | sed 's/^\([0-7]\?[0-9][0-9]\?\))/\1 )/' | awk '($1 < 778) {print $0}' | sed 's/^\([0-7]\?[0-9][0-9]\?\) ).*/\1,/' | tr --delete \\n gives 21,23,.
    – Ned64
    Jun 15 '15 at 13:03
  • 1
    @Masi On FreeBSD, please try sed -E ... or sed -r ... instead of just sed ... - does that work? You could also try to install GNU sed for better compatability to the Linux version (If desired! Nothing against BSD!).
    – Ned64
    Jun 15 '15 at 21:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.