5

I have the following bash command which fetches and block XML from a single column in mysql and feeds it into xmllint to prettify it.

mysql --format csv --skip-column-names -e "select xmldata from mytable limit 1;" | xmllint --format -

So far so good, but it only works for one row at a time. I would like to adapt this so each line in the SQL query output is fed in to a separate call to xmlint.

I know this can be done with a loop in a bash script -- but I'd like to do it in a one-liner if possible. Supposedly this can be done with xargs but I can't figure it out.

2 Answers 2

6
mysql --format csv --skip-column-names \
    -e "select xmldata from mytable limit 1;" \
    | while IFS= read -r line; do xmllint --format - <<<"$line"; done

Split for easier reading, obviously you don't need to. The <<<$line is a herestring, which feeds the contents of $line to xmllint as stdin.

7
  • +1 for herestring, I've always done this as while read line; do echo $line | xmllint...
    – Kyle Smith
    Commented Feb 8, 2012 at 22:18
  • Previously the last line of the answer was written: while read line; do xmllint --format - <<<$line; done ... that worked fine for me... why was it changed and what's the difference? Commented Feb 9, 2012 at 3:44
  • @frankadelic it's almost always best to quote a variable when you use it, so Gilles added quotes here.
    – Kevin
    Commented Feb 9, 2012 at 3:51
  • Right, but why was IFS= added? And what is read -r ? Commented Feb 9, 2012 at 3:53
  • @gilles before I posted, I checked and it didn't break on anything I could find without the quotes. Can you give an example that breaks an unquoted herestring?
    – Kevin
    Commented Feb 9, 2012 at 3:53
0

This is possible with xargs, but xargs would pass each line as an argument to xmllint, not on its standard input. You would need to have xargs invoke a shell to feed the text to xmllint.

mysql … | xargs -L 1 sh -c 'echo "$0" | xmllint --format -'

A shell loop is the easiest method. The canonical way to loop over lines is while IFS= read -r line; do ….

mysql … |
while IFS= read -r line; do printf '%s\n' "$line" | xmllint --format -; done

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .