2

Say I have these two files:

inp

11 hello
22 wonderful
33 beach
44 today
55 is
66 great

pats

11
44
55

I want to do something in inp, but only for lines that are in pats. E.g. say I want to append + at the end. I'd like the end result to be

out

11 hello+
22 wonderful
33 beach
44 today+
55 is+
66 great

Is there an easy way to do this with sed, awk or such? By easy I'd like not to have to write a (e.g. python) program, I'm more looking for something such as grep -f pats inp + sed 's/$/+/' together.

Edit:

I'd like it to work with pattern found anywhere in the line, e.g.:

inp

11 hello
wonderful22
beach 33 front
to44day
is55
gr 66 eat

pats

11
44
55

out

11 hello+
wonderful22
beach 33 front
to44day+
is55+
gr 66 eat
2

bash syntax:

sed -f <(printf 's/^%d\>.*/&+/\n' $(<pats)) inp

The part inside <() part prints out a sed program to transform the appropriate lines:

$ printf 's/^%d\>.*/&+/\n' $(<pats)
s/^11\>.*/&+/
s/^44\>.*/&+/
s/^55\>.*/&+/

The <() syntax is bash process substitution, so you can take the output of a command and work with it like it comes from a file. Then we have sed -f sed_program inp to actually transform the file

2
awk 'NR==FNR {pats[$1]++; next} $1 in pats {$2=$2"+"} 1' pats inp
11 hello+
22 wonderful
33 beach
44 today+
55 is+
66 great

To check for a match anywhere in each line of inp, you could use an essentially similar approach, but extracting the portion to compare using match

awk 'NR==FNR {pats[$1]++; next} match($0,/[0-9]+/) && substr($0,RSTART,RLENGTH) in pats {$0=$0"+"} 1' pats inp2
11 hello+
wonderful22
beach 33 front
to44day+
is55+
gr 66 eat

(If you want to match against arbitrary patterns from the pats file, then a different approach would be required e.g. looping over the elements of the pats array explicitly.)

  • Thanks, nice idea, +1 - would this work for search instead of match by position? I.e. say numbers are not always in the first column, but can be anywhere? – levant pied Oct 11 '16 at 23:20
  • @levantpied the same general method can likely be applied in that case - the specifics would depend on what exactly you mean by "anywhere" – steeldriver Oct 12 '16 at 0:04
  • Thanks - what I meant by anywhere is basically a string search instead of using $1. Or to put it another way, I want matching similar to awk '/pat1|pat2|...|patN/'. – levant pied Oct 12 '16 at 12:29
  • @levantpied sorry, that's still unclear to me - the best thing IMHO would be to edit your question to include examples - or post a new question if you have a significantly different requirement. – steeldriver Oct 12 '16 at 12:37
  • Edited the question with another example. – levant pied Oct 12 '16 at 12:53
0

try this...

awk 'NR==FNR{Arr[$0];next}{for(i=1;i<=NF;i++)for(j in Arr)if(match($i,j)){F=1;$0=$0"+"}else{F=0}}1' pat.txt input.txt
    11 hello+
    wonderful22
    beach 33 front
    to44day+
    is55+
    gr 66 eat

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.