Search code examples
bashpipeechonewlinexargs

How does xargs format the input of $'\n'?


Problem

(1) Given a string, I replace spaces with $'\n' using sed:

echo "one two" | sed 's/ /$'"'"'\\n'"'"'/g'

This outputs:

# one$'\n'two

(2) Note that echoing this output of (1):

echo one$'\n'two

results in:

# one
# two

(3) I echo the output of (1) in another way, by piping the output of (1) into xargs echo:

echo "one two" | sed 's/ /$'"'"'\\n'"'"'/g' | xargs echo

But I don't get the same output as (2):

# one$\ntwo

Question

What does xargs do when formatting the input of a string containing $'\n'?

Why is echoing a string with $'\n' not the same as using xargs echo on the same string?


Solution

  • When you write

    echo one$'\n'two
    

    at the command line, bash replaces the "$'\n'" with a newline. But when you pass it to xargs no such replacement can happen.

    But piping it to xargs will still not do what you want, since by default xargs uses the newline as an argument separator:

    $ echo "one two" | tr ' ' '\n' | xargs echo
    one two
    

    You must tell xargs to use a different separator, even if it is a bogus one:

    $ echo "one two" | tr ' ' '\n' | xargs -0 echo
    one
    two