1

Can sed or awk do this? What I want do to is delete everything not matching this pattern '(something).swf'

It doesn't need to be these commands, and I'm kind of new. The text processing is via the terminal so I would prefer if it didn't just display the output but saved it to a text file.

Example.

On an input like:

Hey stackoverflow im 23 years old 'lol.swf' and '33.swf'

It should output:

'lol.swf'
'33.swf'
3
  • 1
    Do you mean every line containing this pattern, or delete the actual pattern leaving the rest of the line. Also, does the removal string include the quotes?
    – Sparhawk
    Aug 8 '14 at 15:44
  • I mean delete everything that is not 'something.swf' Example: Hey stackoverflow im 23 years old 'lol.swf' and '33.swf' would become 'lol.swf' '33.swf' Yes, it includes 'x2 Aug 8 '14 at 15:47
  • If anyone knows how, I'd love to see a simple sed or awk version too. Something like sed -n "s/.*\('[^']*\.swf'\).*/\1/p" works, but fails on multiple matches in a single line.
    – Sparhawk
    Aug 8 '14 at 16:03
4

I would just use grep (here assuming GNU grep):

grep -o "'[^']*\.swf'" input.txt > output.txt

Explanation

  • -o prints only the matching part, not the whole line.
  • "'[^']*\.swf'" is the pattern to match, enclosed in " so that you can have ' in it. It matches an initial ', followed by [^']*, which is an indeterminate number of non-' characters, followed by .swf (N.B. you have to escape the . as \., since . has a special meaning in regular expressions.
  • input.txt is the input file to read.
  • > output.txt will redirect output to this file. If you remove this part you can preview the output on the screen.

Alternative

If GNU grep isn't installed, you can try the following (inspired by terdon's replacement idea).

tr -d '\n' <input.txt | tr "'" '\n' | head -n -1 | tail -n +2 | grep '.*\.swf$' > output.txt

Explanation

  • tr -d '\n' <input.txt will read from input.txt, then remove all line breaks (\n).
  • tr "'" '\n' will convert all ' into line breaks. This means that each line was previously surrounded by '.
  • head -n -1 | tail -n +2. However, if the original text file started with something.swf' or ended with 'something.swf, these would be on their own line, despite only having one ', and would be erroneously detected by the following grep. If, however, the first or last string correctly had both quotes, there would be an extra line break at the beginning or end at this stage. Hence, this segment of code strips off the last line and first line to only match this scenario.
  • grep '\.swf$' will match lines that end with .swf.
4
  • sorry, looks like I edited at the same time as you... Aug 8 '14 at 15:55
  • Ha, no worries @StéphaneChazelas. Thanks for the edit, too. :)
    – Sparhawk
    Aug 8 '14 at 15:56
  • Glad to help @user3922897. Have a read up on regular expressions if you get a chance. They are truly wonderful!
    – Sparhawk
    Aug 8 '14 at 15:57
  • 1
    @user3922897 If this answer solves your issue please take a minute and click the check mark under the vote count to the left, instead of leaving a thank you comment. This will signify to everyone that your issue's been resolved and is the way that thanks are expressed in the site.
    – terdon
    Aug 8 '14 at 16:03
3

If your grep doesn't support -o, you can use perl instead:

perl -lne "print for /'.*?\.swf'/g" < in.txt > out.txt

With sed:

sed -n "/\('[^']*\.swf'\)/{s//\n\1\n/;s/.*\n\(.*\n\)/\1/;P;D;}"

Which is the equivalent of:

awk '
  {
    while(match($0, '"/'[^']*\.swf'/"')) {
      print substr($0, RSTART, RLENGTH)
      $0 = substr($0, RSTART+RLENGTH)
    }
  }'

(D in sed loops with the first line of the pattern space removed).

1
  • Wow, nice sed… Could you possibly explain what's going on? +1
    – Sparhawk
    Aug 8 '14 at 16:11
2

Here's an awk approach:

$ awk "{for(i=1;i<=NF;i++){if(\$i~/'[^']*.swf'/){print \$i}}}" file
'lol.swf'
'33.swf'

And a non-GNU grep one. Just change all spaces to newlines and use normal grep:

$ sed 's/ /\n/g' file | grep "'[^']*.swf'"
'lol.swf'
'33.swf'
5
  • +1 Nice one! Could you possibly explain the awk code? Good idea with the grep too. (FWIW it's slightly faster to use tr. $ time for i in {1..1000} ; do sed 's/ /\n/g' file > /dev/null; done vs. $ time for i in {1..1000} ; do tr ' ' '\n' <file > /dev/null; done for me is 3.108s vs. 1.451s.)
    – Sparhawk
    Aug 8 '14 at 16:17
  • That assumes they are blank separated though (wouldn't work on 'a.swf','b.swf' for instance). Aug 8 '14 at 16:19
  • @StéphaneChazelas indeed. It assumes each is a separate word.
    – terdon
    Aug 8 '14 at 16:19
  • Could you break on ' instead, then insert it back after the grep?
    – Sparhawk
    Aug 8 '14 at 16:36
  • I added an alternative inspired by your sed idea, breaking on '.
    – Sparhawk
    Aug 9 '14 at 1:03

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.