bash 别名中的转义字符
Escaping characters in bash alias
这是别名:
# make a tmux session in working dir with the name of the dir
alias th='tmux new -s $(pwd | tr '\/' '\n' | tail -n 1)'
由于转义字符或别名内的 '
、单引号,它不起作用。打印出来
$ type --all th
th is aliased to `tmux new -s $(pwd | tr / n | tail -n 1)'
看起来它只是剥离了 '
和 \
。
我最终通过将单引号更改为双引号来修复它。
# make a tmux session in working dir with the name of the dir
alias th='tmux new -s $(pwd | tr "\/" "\n" | tail -n 1)'
我的问题是之前的 on 到底是怎么工作的?不应该 bash 抛出解析错误。
您嵌入的单引号未被视为嵌入,它们终止了先前的字符串并开始了新的字符串。您的第一次尝试被视为 tmux new -s $(pwd | tr
、\/
、' '、\n
和 | tail -n 1)
的串联。将所有这些放在一起并处理转义,你会得到你在 type
命令的输出中看到的内容。
最佳建议:不要。
改用函数:
th() { tmux new -s "${PWD##*/}" "$@"; }
${PWD##*/}
是一个 parameter expansion,它从 $PWD
.
的内容中去除包括最后一个 /
在内的所有内容
替代方法:文字引述
您的原始代码中的问题在于它包含 syntactic 引号 -- 由 shell 解析的引号以确定单引号解析规则的开始和结束位置 - - 在您真正想要的是 文字 引号的地方,这些引号被视为数据(因此成为别名的一部分)。
使这些引号成为文字的一种方法是使用 $''
引用形式,它允许您使用文字反斜杠来转义内部引号,使它们成为文字而不是句法:
alias th=$'tmux new -s $(pwd | tr \'\\/\' \'\n\' | tail -n 1)'
请注意,当使用 $''
时,文字反斜杠也需要转义(因此,写成 \
而不是 \
)。
解释:为什么
POSIX shell 语言中的字符串引用是逐个字符确定的。因此,在以下情况下:
'$foo'"$((1+1))"baz
...$foo
是单引号,因此被视为文字字符串,$((1+1))
是双引号,因此有资格被视为算术扩展,baz
未加引号——即使所有这三个都连接在一起形成一个单词 ($foo2baz
)。
这些引用都是句法——它们是对shell的指令——而不是文字(这会意味着它们将成为该字符串评估的数据的一部分)。
这如何适用于您之前的命令
在
alias th='tmux new -s $(pwd | tr '\/' '\n' | tail -n 1)'
...tr
end 参数中的单引号 单引号从别名的开头开始。因此,\/
和 \n
在未引用的上下文中计算(其中 \/
变为 /
,而 \n
变为 n
)- - 因为如上所述,多个不同引号的子字符串只能连接成一个更大的字符串,所以您得到的是先前的命令,而不是别名。
这是别名:
# make a tmux session in working dir with the name of the dir
alias th='tmux new -s $(pwd | tr '\/' '\n' | tail -n 1)'
由于转义字符或别名内的 '
、单引号,它不起作用。打印出来
$ type --all th
th is aliased to `tmux new -s $(pwd | tr / n | tail -n 1)'
看起来它只是剥离了 '
和 \
。
我最终通过将单引号更改为双引号来修复它。
# make a tmux session in working dir with the name of the dir
alias th='tmux new -s $(pwd | tr "\/" "\n" | tail -n 1)'
我的问题是之前的 on 到底是怎么工作的?不应该 bash 抛出解析错误。
您嵌入的单引号未被视为嵌入,它们终止了先前的字符串并开始了新的字符串。您的第一次尝试被视为 tmux new -s $(pwd | tr
、\/
、' '、\n
和 | tail -n 1)
的串联。将所有这些放在一起并处理转义,你会得到你在 type
命令的输出中看到的内容。
最佳建议:不要。
改用函数:
th() { tmux new -s "${PWD##*/}" "$@"; }
${PWD##*/}
是一个 parameter expansion,它从 $PWD
.
/
在内的所有内容
替代方法:文字引述
您的原始代码中的问题在于它包含 syntactic 引号 -- 由 shell 解析的引号以确定单引号解析规则的开始和结束位置 - - 在您真正想要的是 文字 引号的地方,这些引号被视为数据(因此成为别名的一部分)。
使这些引号成为文字的一种方法是使用 $''
引用形式,它允许您使用文字反斜杠来转义内部引号,使它们成为文字而不是句法:
alias th=$'tmux new -s $(pwd | tr \'\\/\' \'\n\' | tail -n 1)'
请注意,当使用 $''
时,文字反斜杠也需要转义(因此,写成 \
而不是 \
)。
解释:为什么
POSIX shell 语言中的字符串引用是逐个字符确定的。因此,在以下情况下:
'$foo'"$((1+1))"baz
...$foo
是单引号,因此被视为文字字符串,$((1+1))
是双引号,因此有资格被视为算术扩展,baz
未加引号——即使所有这三个都连接在一起形成一个单词 ($foo2baz
)。
这些引用都是句法——它们是对shell的指令——而不是文字(这会意味着它们将成为该字符串评估的数据的一部分)。
这如何适用于您之前的命令
在
alias th='tmux new -s $(pwd | tr '\/' '\n' | tail -n 1)'
...tr
end 参数中的单引号 单引号从别名的开头开始。因此,\/
和 \n
在未引用的上下文中计算(其中 \/
变为 /
,而 \n
变为 n
)- - 因为如上所述,多个不同引号的子字符串只能连接成一个更大的字符串,所以您得到的是先前的命令,而不是别名。