The power of shell pipeline is so great that sometimes fails me.
Example
Just as an example, the pipeline
echo abc > file.txt
cat file.txt | sed 's/a/1/' > file.txt
gives me an empty file.txt
. Realizing that the shell probably calls >
first, I made a change:
echo abc > file.txt
{cat file.txt | sed 's/a/1/'} > file.txt
Again it surprises me by another empty file file.txt
. An ugly way that finally works is
echo abc > file.txt
echo $(cat file.txt | sed 's/a/1') > file.txt
which forces the shell to run a subshell first, and then redirect.
Question
While I'm aware of better practice of sed
, which allows you to get rid of echo
, cat
, grep
.. etc, what I am curious about here is to learn shell's grammar completely. This questions is not about how to fix the particular problem above.
Q1(EDIT: off-topic) Is there a good resource for me to learn the grammar?
I'm afraid that different shells could have different grammars, so
Q2 Can I make shell verbose, and see clearly what it is doing every completely every single time I run a command?
Q3(EDIT: off-topic) Any other advice on good practices? Thank you!
bash -x script.sh
or in an interactive shellset -x
– glenn jackman May 13 '20 at 20:20exec 3<file.txt; rm file.txt; sed 's/a/1/' <&3 >file.txt
(At least withbash
. Not 100% sure aboutsh
.) But of course, usingsed
's-i
option is better. – ikegami May 14 '20 at 04:44sh
. (Well, I tested withdash
, which I believe is suppose to be a compliant implementation ofsh
?) – ikegami May 14 '20 at 05:22/bin/sh
is dash, but it can differ by distro. But theoretically any POSIX-compliant version of/bin/sh
haveexec
( listed in built-in spec ) – Sergiy Kolodyazhnyy May 14 '20 at 07:02