2

INPUT

AA XXX Y1Y ZZZ GG dhz
rr (AAAa) XXX Y2Y ZZZ TT GGGG UU

OUTPUT

Y1Y
Y2Y

The input lines could vary.. only the XXX before the Y1Y and the ZZZ after Y1Y is constant (they are the neighbors of XXX and ZZZ like this). Y1Y could be anything, ex.: Y1Y, Y2Y, Y1T, etc.

Q: how can I get the OUTPUT with awk or sed or grep? (or are there any better tool for this?)

UPDATE (problem): why doesn't it works when having "." in the Y1Y?

[user@notebook ~] echo 'XXX Y1Y ZZZ' | grep -Po "(?<=XXX )(\w+)(?= ZZZ)"
Y1Y
[user@notebook ~] echo 'XXX Y1.Y ZZZ' | grep -Po "(?<=XXX )(\w+)(?= ZZZ)"
[user@notebook ~] 
  • no, and I updated the "INPUT" – gasko peter Oct 3 '13 at 13:34
  • Are the neighbors always XXX and ZZZ? – slm Oct 3 '13 at 13:40
  • yes, as I wrote! – gasko peter Oct 3 '13 at 13:40
  • Yes but it isn't clear whether XXX and ZZZ are stand ins for something else are literally XXX and ZZZ. Just my $0.02. – slm Oct 3 '13 at 13:41
  • 1
    OK, see my answer, that should be all you need. – slm Oct 3 '13 at 13:44
1

You can use grep and the PCRE facility it provides to do this:

$ grep -Po "(?<=XXX )\S+(?= ZZZ)" data.txt 
Y1Y
Y2Y

Details

This solution makes use of the lookbehind and lookahead feature of PCRE, which can match fixed length strings.

The above looks behind every \w+ to see if it's XXX and head of every \w+ seeing if it's ZZZ. If it is then it's a match. The -o switch to grep tells it to only print the matches, i.e. \w+.

Followup, can you do it with sed?

I don't think that this problem can be solved using sed. There are 2 approaches as I see it.

  1. save potential matches in a side variable, if you encounter ZZZ, then print them
  2. s/XXX ..our string.. ZZZ/ ..our string../

No. 1 seems like a fair amount of work so I'm not going to even attempt it. Here's what happens with approach No. 2.

$ sed 's/.*XXX \(.*\) ZZZ.*/\1/' data.txt 
Y1Y
Y2Y
AAAa YXX Y2Y ZZZ TT GGGG UU

So it can find the matches just fine, but it doesn't do anything for lines that don't match. There might be a way to instruct sed to delete these lines, in which case this would be an alternate solution.

  • is it impossible to do this in sed? :D – gasko peter Oct 3 '13 at 13:50
  • @gaskopeter - I think it would be trickier b/c sed is a line editor, so you'd have to save the potential matches in a temp. variable until you can confirm that the sub strings after the match are ZZZ. – slm Oct 3 '13 at 13:53
  • @gaskopeter - your welcome, and thank your for the Q. – slm Oct 3 '13 at 13:54
  • I tested it and got 1 problem, sorry:D – gasko peter Oct 3 '13 at 14:00
  • @gaskopeter - yes the problem's with the \w+. That matches only word characters (A-Z0-9). Period isn't one of them. What characters are allowed for the matched substring? – slm Oct 3 '13 at 14:02

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.