Bash – Unexpected output of xargs

bashpipesedxargs

The statement below should print afc abc but it prints abc abc instead. I tried many times but every time same result Don't know why this happens could anyone explain and help me?

echo abc|xargs -i{} echo $(echo {}|sed 's/b/f/g') {}

Best Answer

Yes it does, because the command substitution is carried out by the shell before the xargs is even started. The echo in the substitution prints the literal string {} for sed to manipulate. sed makes no changes to it, and the result is that xargs sees

echo {} {}

Instead:

echo 'abc' | xargs -I{} bash -c 'echo "$(sed "s/b/f/g" <<<"$1")" "$1"' bash {}

Here, we prevent the shell from evaluating the command substitution by embedding it in an in-line script. The script is given the command line argument (abc) from xargs and manipulates it as "$1".

It would be even better to use printf in case you'd get the idea to replace the a with a dash and the other characters to something that would be interpreted as an option to echo:

echo 'abc' | xargs -I{} bash -c 'printf "%s %s\n" "$(sed "s/b/f/g" <<<"$1")" "$1"' bash {}

Or, without sed:

echo 'abc' | xargs -I{} bash -c 'printf "%s %s\n" "${1//b/f}" "$1"' bash {}

Or, you could just do it with sed alone (at least in this simple example):

echo 'abc' | sed 'h; s/b/f/g; G; s/\n/ /'
Related Question