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.

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.

  • +1 for herestring, I've always done this as while read line; do echo $line | xmllint... – Kyle Smith Feb 8 '12 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? – frankadelic Feb 9 '12 at 3:44
  • @frankadelic it's almost always best to quote a variable when you use it, so Gilles added quotes here. – Kevin Feb 9 '12 at 3:51
  • Right, but why was IFS= added? And what is read -r ? – frankadelic Feb 9 '12 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 Feb 9 '12 at 3:53

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

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.