The first command below produces each number on a separate line, and I would expect the second command to do the same thing because the only difference between the two is that we are using echo '1 2 3' and echo {1..3} (both of which produce the same output). But, the second command produces the numbers that are separated by tabs instead of new lines. Why?
Furthermore, notice that the only difference between the second and the third commands is that we are passing the result to paste via process substitution, but without that, it shows the expected result, which could imply that it is a paste related issue, but I don't quite see what the issue is.
§ paste <(echo '1 2 3' | tr ' ' '\t' | tr '\t' '\n') 1 2 3 § paste <(echo {1..3} | tr ' ' '\t' | tr '\t' '\n') 1 2 3 § echo {1..3} | tr ' ' '\t' | tr '\t' '\n' 1 2 3 I tried to see the output produced at the end of the process substitution pipeline to see what was being output, and it does indeed appear to be the same.
§ paste <(echo {1..3} | tr ' ' '\t' | tr '\t' '\n' | tee /dev/stderr) > /dev/null 1 2 3 § paste <(echo '1 2 3' | tr ' ' '\t' | tr '\t' '\n' | tee /dev/stderr) > /dev/null 1 2 3 If it matters, here are the versions of the tools:
§ which tr paste /usr/local/opt/coreutils/libexec/gnubin/tr /usr/local/opt/coreutils/libexec/gnubin/paste § tr --version tr (GNU coreutils) 9.1 Copyright (C) 2022 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>. Written by Jim Meyering. § paste --version paste (GNU coreutils) 9.1 Copyright (C) 2022 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>. Written by David M. Ihnat and David MacKenzie. § bash --version bash --version GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin20) Copyright (C) 2007 Free Software Foundation, Inc. § sw_vers ProductName: macOS ProductVersion: 11.7.10 BuildVersion: 20G1427 I am on macOS, but use GNU utils installed via brew.
Addition debug information requested by comments with set -x active:
§ paste <(echo {1..3} | tr ' ' '\t' | tr '\t' '\n') + paste /dev/fd/63 /dev/fd/62 /dev/fd/61 ++ echo 1 ++ echo 3 ++ tr ' ' '\t' ++ tr ' ' '\t' ++ tr '\t' '\n' ++ tr '\t' '\n' ++ echo 2 ++ tr ' ' '\t' ++ tr '\t' '\n' 1 2 3 § paste <(echo {1..3} | tr ' ' '\n') + paste /dev/fd/63 /dev/fd/62 /dev/fd/61 ++ echo 1 ++ tr ' ' '\n' ++ echo 2 ++ echo 3 ++ tr ' ' '\n' ++ tr ' ' '\n' 1 2 3 § echo {1..3} | tr ' ' '\n' | paste + tr ' ' '\n' + echo 1 2 3 + paste 1 2 3 And hexdump output:
§ paste <(echo {1..3} | tr ' ' '\n') | hexdump -C 00000000 31 09 32 09 33 0a |1.2.3.| 00000006 § echo {1..3} | tr ' ' '\n' | paste | hexdump -C 00000000 31 0a 32 0a 33 0a |1.2.3.| 00000006
"\t"and"\n".tris able to interpret the special characters. I do not intend for the shell to do the interpolation, but even with double quotes, it makes no difference, i.e.,paste <(echo {1..3} | tr " " "\t" | tr "\t" "\n")produces a tab-separated list like the second command.echo {1..3} | tr ' ' '\t' | tr '\t' '\n' | pasteproduces the correct output too. So, piping topasteworks fine, but usingpastewith process substitution seemingly interprets the lines as columns (?). But, why?{1..3}but I’m not using macOS.'\t'and"\t"differently, both just mean a literal\followed by a literalt. You would need$'\t'for the shell to interpret that as a tab. Fortr, single and double quotes make no difference. Compareecho {1..3} | tr ' ' '\t'withecho {1..3} | tr ' ' \\torecho {1..3} | tr ' ' "\t"and you will see all three produce the same output.