奇怪的 bash 行为(管道、su、zsh)- 评论错误和用户未更改
Strange bash behaviour (pipe, su, zsh) - Errors in comments and user not changed
我正在编写一个脚本来安装和配置用户、zsh 和 zprezto。为了我的需要,我编写了一些代码,应该以用户 X(使用 su)和 zsh shell.
执行多个命令
行为不是我所期望的,所以我需要一些关于这段代码的解释。
su admin -c zsh << EOF
echo '$USER';
echo '$SHELL';
EOF
此代码仅用于测试:我需要确保命令以用户管理员身份和 zsh shell 中执行。但是,输出是:
root
/bin/zsh
我只是不明白:su 不应该在执行命令之前更改用户吗?
即使有这个问题,我也尝试编写我的代码,但我遇到了另一个奇怪的行为:
cat << EOF | su "admin" -c zsh
local file="${ZDOTDIR:-$HOME}/.zpreztorc"
echo "File for $USER : ${ZDOTDIR:-$HOME}/.zpreztorc"
setopt clobber; # Do not warn when overwritting file
modules=$(cat "$file" | grep -Pzo "(?s)(zstyle ':prezto:load' pmodule\N*.)([\s\t]*'[a-z]*'[\s\t]*\\.)*[\s\t]*'[a-z]*'");
firstLineNumber=$(cat "$file" | grep -Fn "$(echo -n "$modules" | head -n 1)" | sed 's/^\([0-9]\+\):.*$//');
lastLineNumber=$(cat "$file" | grep -Fn $(echo -n "$modules" | tail -n 1) | sed 's/^\([0-9]\+\):.*$//');
for module in ${prezto_modules[@]}; do
modules="$modules \
'$module'";
done
fileContent=$(cat "$file" | sed "$firstLineNumber,$lastLineNumber d");
echo -n "$fileContent" | head -n "$((firstLineNumber-1))" > "$file";
echo "$modules" >> "$file";
echo -n "$fileContent" | tail -n "+$((firstLineNumber))" >> $file;
cat "$file";
EOF
然而,输出也很奇怪:
cat: '': No such file or directory
cat: '': No such file or directory
cat: '': No such file or directory
grep: loaded: No such file or directory
grep: loaded: No such file or directory
grep: loaded: No such file or directory
grep: loaded: No such file or directory
grep: loaded: No such file or directory
grep: loaded: No such file or directory
grep: loaded: No such file or directory
grep: autoloaded: No such file or directory
grep: autoloaded: No such file or directory
grep: autoloaded: No such file or directory
grep: autoloaded: No such file or directory
grep: autoloaded: No such file or directory
grep: autoloaded: No such file or directory
cat: '': No such file or directory
sed: -e expression n°1, caractère 1: commande inconnue: `,'
tail: incorrect line number: « + »
File for root : /root/.zpreztorc
我试图翻译法语中的错误,不知道 sed 的确切翻译,所以我就按原样翻译。
但是错误本身并不奇怪,看看我的第一个回显行:
回声"File for $USER : ${ZDOTDIR:-$HOME}/.zpreztorc" --> "File for root : /root/.zpreztorc"
除了我们是 root 之外,它显示为输出的最后一行。这意味着在执行代码之前发现错误,对吗?
更奇怪的是:如果我们注释代码,错误仍然存在:
su "admin" -c zsh << EOF
# modules=$(cat "$file" | grep -Pzo "(?s)(zstyle ':prezto:load' pmodule\N*.)([\s\t]*'[a-z]*'[\s\t]*\\.)*[\s\t]*'[a-z]*'");
EOF
输出是:
cat: '': No such file or directory
你怎么解释?
谢谢
此处带有 << MARKER
的文档将被解释为双引号字符串,而 << 'MARKER'
将被解释为单引号字符串:
su admin -c zsh << 'EOF'
echo "$USER" "this is admin"
EOF
虽然使用 << MARKER
在作为标准输入发送之前被扩展
su admin -c zsh << EOF
echo "$USER" "this is the current user single quotes doesn't prevent it"
echo '$USER' 'This is still expanded before send as stdin to zsh'
EOF
有关详细信息,请参阅 man bash | grep --max-count=1 '<<' -A 11
:
<<[-]word
here-document
delimiter
No parameter and variable expansion, command substitution, arithmetic
expansion, or pathname expansion is performed on word. If any charac‐
ters in word are quoted, the delimiter is the result of quote removal
on word, and the lines in the here-document are not expanded. If word
is unquoted, all lines of the here-document are subjected to parameter
expansion, command substitution, and arithmetic expansion, the charac‐
ter sequence \<newline> is ignored, and \ must be used to quote the
characters \, $, and `.
我正在编写一个脚本来安装和配置用户、zsh 和 zprezto。为了我的需要,我编写了一些代码,应该以用户 X(使用 su)和 zsh shell.
执行多个命令行为不是我所期望的,所以我需要一些关于这段代码的解释。
su admin -c zsh << EOF
echo '$USER';
echo '$SHELL';
EOF
此代码仅用于测试:我需要确保命令以用户管理员身份和 zsh shell 中执行。但是,输出是:
root
/bin/zsh
我只是不明白:su 不应该在执行命令之前更改用户吗?
即使有这个问题,我也尝试编写我的代码,但我遇到了另一个奇怪的行为:
cat << EOF | su "admin" -c zsh
local file="${ZDOTDIR:-$HOME}/.zpreztorc"
echo "File for $USER : ${ZDOTDIR:-$HOME}/.zpreztorc"
setopt clobber; # Do not warn when overwritting file
modules=$(cat "$file" | grep -Pzo "(?s)(zstyle ':prezto:load' pmodule\N*.)([\s\t]*'[a-z]*'[\s\t]*\\.)*[\s\t]*'[a-z]*'");
firstLineNumber=$(cat "$file" | grep -Fn "$(echo -n "$modules" | head -n 1)" | sed 's/^\([0-9]\+\):.*$//');
lastLineNumber=$(cat "$file" | grep -Fn $(echo -n "$modules" | tail -n 1) | sed 's/^\([0-9]\+\):.*$//');
for module in ${prezto_modules[@]}; do
modules="$modules \
'$module'";
done
fileContent=$(cat "$file" | sed "$firstLineNumber,$lastLineNumber d");
echo -n "$fileContent" | head -n "$((firstLineNumber-1))" > "$file";
echo "$modules" >> "$file";
echo -n "$fileContent" | tail -n "+$((firstLineNumber))" >> $file;
cat "$file";
EOF
然而,输出也很奇怪:
cat: '': No such file or directory
cat: '': No such file or directory
cat: '': No such file or directory
grep: loaded: No such file or directory
grep: loaded: No such file or directory
grep: loaded: No such file or directory
grep: loaded: No such file or directory
grep: loaded: No such file or directory
grep: loaded: No such file or directory
grep: loaded: No such file or directory
grep: autoloaded: No such file or directory
grep: autoloaded: No such file or directory
grep: autoloaded: No such file or directory
grep: autoloaded: No such file or directory
grep: autoloaded: No such file or directory
grep: autoloaded: No such file or directory
cat: '': No such file or directory
sed: -e expression n°1, caractère 1: commande inconnue: `,'
tail: incorrect line number: « + »
File for root : /root/.zpreztorc
我试图翻译法语中的错误,不知道 sed 的确切翻译,所以我就按原样翻译。 但是错误本身并不奇怪,看看我的第一个回显行:
回声"File for $USER : ${ZDOTDIR:-$HOME}/.zpreztorc" --> "File for root : /root/.zpreztorc" 除了我们是 root 之外,它显示为输出的最后一行。这意味着在执行代码之前发现错误,对吗?
更奇怪的是:如果我们注释代码,错误仍然存在:
su "admin" -c zsh << EOF
# modules=$(cat "$file" | grep -Pzo "(?s)(zstyle ':prezto:load' pmodule\N*.)([\s\t]*'[a-z]*'[\s\t]*\\.)*[\s\t]*'[a-z]*'");
EOF
输出是:
cat: '': No such file or directory
你怎么解释? 谢谢
此处带有 << MARKER
的文档将被解释为双引号字符串,而 << 'MARKER'
将被解释为单引号字符串:
su admin -c zsh << 'EOF'
echo "$USER" "this is admin"
EOF
虽然使用 << MARKER
在作为标准输入发送之前被扩展
su admin -c zsh << EOF
echo "$USER" "this is the current user single quotes doesn't prevent it"
echo '$USER' 'This is still expanded before send as stdin to zsh'
EOF
有关详细信息,请参阅 man bash | grep --max-count=1 '<<' -A 11
:
<<[-]word
here-document
delimiter
No parameter and variable expansion, command substitution, arithmetic
expansion, or pathname expansion is performed on word. If any charac‐
ters in word are quoted, the delimiter is the result of quote removal
on word, and the lines in the here-document are not expanded. If word
is unquoted, all lines of the here-document are subjected to parameter
expansion, command substitution, and arithmetic expansion, the charac‐
ter sequence \<newline> is ignored, and \ must be used to quote the
characters \, $, and `.