6

I have a file with a lot of lines like this

/item/pubDate=Sun, 23 Feb 2014 00:55:04 +010

If I execute this

echo "/item/pubDate=Sun, 23 Feb 2014 00:55:04 +010" | grep -Po "(?<=\=).*"

Sun, 23 Feb 2014 00:55:04 +010

I get the correct date (all in one line). Now I want to try this with a lot of dates in a xml file. I use this and it's ok.

xml2 < date_list | egrep "pubDate" | grep -Po "(?<=\=).*"
Fri, 22 Jan 2016 17:56:29 +0100
Sun, 13 Dec 2015 18:33:02 +0100
Wed, 18 Nov 2015 15:27:43 +0100
...

But now I want to use the date in a bash program and I get this output

for fecha in $(xml2 < podcast | egrep "pubDate" | grep -Po "(?<=\=).*"); do echo $fecha; done
    Fri,
    22
    Jan
    2016
    17:56:29
    +0100
    Sun,
    13
    Dec
    2015
    18:33:02
    +0100
    Wed,
    18
    Nov
    2015
    15:27:43
    +0100

I want the date output in one line (in variable fecha) how the first and second examples but I don't know how to do it.

  • xml2 < date_list | egrep "pubDate" | grep -Po "(?<=\=).*" | while read fecha ... – Jeff Schaller Feb 16 '16 at 21:40
7

Do it this way instead:

while IFS= read -r fecha; do
    echo $fecha
done < <(xml2 < podcast | egrep "pubDate" | grep -Po "(?<=\=).*")

Bash will separate "words" to loop through by characters in the Internal Field Separator ($IFS). You can temporarily disable this behavior by setting IFS to nothing for the duration of the read command. The pattern above will always loop line-by-line.

<(command) makes the output of a command look like a real file, which we then redirect into our read loop.

$ while IFS= read -r line; do echo $line; done < <(cat ./test.input)
Fri, 22 Jan 2016 17:56:29 +0100
Sun, 13 Dec 2015 18:33:02 +0100
Wed, 18 Nov 2015 15:27:43 +0100
  • Is there a reason you turn xml2 < podcast | egrep "pubDate" | grep -Po "(?<=\=).*" into a "file" instead of piping its output to the while loop? If so, could you explain? – gardenhead Feb 17 '16 at 3:24
  • 1
    @gardenhead, read this, should answer the question in your comment there. – Wildcard Feb 17 '16 at 8:16
2
xml2 < date_list | egrep "pubDate" | grep -Po "(?<=\=).*" \
| while read L
  do
    echo $L
  done

read breaks on lines, and doesn't split words unless asked. :-)

However, tackling XML with regular expressions is bringing a knife to a gunfight. It's very easy to construct valid XML that the above pipeline will either miss, or capture incorrectly.

If you deal with much XML, you really want to get comfortable with a SAX parser.

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.