0

My question is basically a follow up question on this topic. I have a file like this:

1000 | line1
100  | line2
10   | line3

I want to do something on $2 if $1 is greater than 20. I wrote something to mimic the 2nd answer but it doesn't work:

for a, b in $(cat file.text|cut -d"|" -f 1,2);
do
if ($1>20) echo $2
done;

How can I achieve this? Thanks!

Kusalananda
  • 333,661

4 Answers4

2

With awk:

$ for param in $(awk '$1 > 20 { print $3 }' inputfile); do ./process.sh "$param"; done
DopeGhoti
  • 76,081
2

You wouldn't really want to parse data in the shell itself, but to use a tool like awk to do it for you.

awk -F '[[:blank:]|]+' '$1 > 20 { print $2 }' file

This instructs awk to treat each line of the file as a set of fields delimited by any number of pipe-symbols or blanks (spaces or tabs). When the first field is greater than 20, the second field is printed.

Related:


If the second column contain blanks, then you may want to use [[:blank:]]*[|][[:blank:]]* as the delimiter:

awk -F '[[:blank:]]*[|][[:blank:]]*' '$1 > 20 { print $2 }' file

The [|] matches a literal pipe symbol, and may be replaced by \\| (if you enjoy backslashes).


The following executes a script with each instance of the second column whose first column is greater than 20 as the command line argument:

awk -F '[[:blank:]]*[|][[:blank:]]*' '$1 > 20 { print $2 }' file |
xargs -I XX ./script.sh XX

With something like -P 4 as an option to xargs, you can run multiple parallel instances of your script at once (four with -P 4).

Kusalananda
  • 333,661
1
awk -F'|' '$1 > 20 { system("/path/to/another/script.sh "$2 }' < file.text

This tells awk to split the input up into fields based on the pipe symbol. Any first field whose value is greater than 20 triggers the system call to ... anything you want. Keep in mind that the argument (here $2, but it could be $0 or any other calculation you do in awk) is passed to the script via a shell call, so if those values can contain shell-special characters, carefully quote it. I'll refer to one of Stéphane's answers for an example of how to do that:

awk 'function escape(s) {
       gsub(/'\''/,"&\\\\&&",s)
       return "'\''" s "'\''"
     }
     { system("/path/to/another/script.sh" escape($2)) }'
Jeff Schaller
  • 67,283
  • 35
  • 116
  • 255
  • Yes this is exactly what I am looking for. I used a work-around like this:awk -F"|" '{if ($1>20) print "script.sh " $2}' |bash. But your solution is better! Thanks! – user3768495 May 04 '18 at 18:17
0

You can try with gnu sed too

sed -E 's/([0-9]*) \| (.*)/[ \1 -gt 20 ] \&\& echo do something with \2/e' infile
ctac_
  • 1,960