bash bash别名中的转义字符
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/42953603/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Escaping characters in bash alias
提问by Charlie OConor
This was the 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)'
It doesn't work because of the escape characters or due to the '
, single quotes, inside the alias. Printing it out
由于转义字符或'
别名内的 , 单引号,它不起作用。打印出来
$ type --all th
th is aliased to `tmux new -s $(pwd | tr / n | tail -n 1)'
It looks like it was just stripping out the '
and \
.
看起来它只是去除了'
and \
。
I eventually fixed it by changing the single quotes to double quotes.
我最终通过将单引号更改为双引号来修复它。
# make a tmux session in working dir with the name of the dir
alias th='tmux new -s $(pwd | tr "\/" "\n" | tail -n 1)'
My question is how did the previous on work at all? Shouldn't bash throw a parsing error.
我的问题是之前的 on 是如何工作的?bash 不应该抛出解析错误。
回答by Charles Duffy
Best Advice: Don't.
最佳建议:不要。
Use a function instead:
改用函数:
th() { tmux new -s "${PWD##*/}" "$@"; }
${PWD##*/}
is a parameter expansionwhich strips everything up to and including the last /
from the contents of $PWD
.
${PWD##*/}
是一个参数扩展,它/
从$PWD
.
Alternate Approach: LiteralQuotes
替代方法:字面引用
The issue in your original code is that it contains syntacticquotes -- ones parsed by the shell to determine where single-quoted parsing rules begin and end -- in places where what you actually want is literalquotes, ones which are treated as data (and thus become part of the alias).
原始代码中的问题在于它包含语法引号——由 shell 解析以确定单引号解析规则开始和结束的位置——在你真正想要的是文字引号的地方,那些被视为数据(从而成为别名的一部分)。
One way to make these quotes literal would be to use the $''
quoting form instead, which lets you use literal backslashes to escape inner quotes, making them literal rather than syntactic:
使这些引号文字化的一种方法是使用$''
引用形式,它允许您使用文字反斜杠来转义内部引号,使它们成为文字而不是语法:
alias th=$'tmux new -s $(pwd | tr \'\\/\' \'\n\' | tail -n 1)'
Note that when using $''
, literal backslashes need to be escaped as well (thus, written as \\
rather than \
).
请注意,在使用时$''
,文字反斜杠也需要转义(因此,写作\\
而不是\
)。
Explanation: Why
解释:为什么
The quoting of strings in POSIX shell languages is determined on a character-by-character basis. Thus, in the case of:
POSIX shell 语言中字符串的引用是在逐个字符的基础上确定的。因此,在以下情况下:
'$foo'"$((1+1))"baz
...$foo
is single-quoted and thus treated as a literal string, $((1+1))
is double-quoted and thus eligible for being treated as arithmetic expansion, and baz
is unquoted -- even though all three of these are concatenated to form a single word ($foo2baz
).
...$foo
是单引号,因此被视为文字字符串,$((1+1))
是双引号,因此有资格被视为算术扩展,并且baz
是不带引号的——即使所有这三个都连接形成一个单词 ( $foo2baz
)。
These quotes are all syntactic-- they're instructions to the shell -- not literal(which would mean they'd be part of the data to which that string evaluates).
这些引号都是句法——它们是对 shell 的指令——而不是文字(这意味着它们将成为该字符串评估的数据的一部分)。
How This Applies To Your Previous Command
这如何适用于您之前的命令
In
在
alias th='tmux new -s $(pwd | tr '\/' '\n' | tail -n 1)'
...the single quotes in the arguments to tr
endthe single quotes started at the beginning of the alias. Thus, \/
and \n
are evaluated in an unquoted context (in which \/
becomes just /
, and \n
becomes just n
) -- and since, as described above, multiple differently-quoted substrings can just be concatenated into a single larger string, you get your prior command, not an alias.
...参数中的单引号tr
结束单引号从别名的开头开始。因此,\/
and\n
在未加引号的上下文中进行评估(其中\/
变为 just /
,然后\n
变为 just n
)——而且,如上所述,多个不同引用的子字符串可以连接成一个更大的字符串,因此您可以得到先前的命令,而不是别名。
回答by Eric Renouf
Your embedded single quotes weren't being treated as embedded, they were terminating previous strings and staring new ones. Your first attempt was being treated as the concatenation of tmux new -s $(pwd | tr
, \/
, ' ', \n
, and | tail -n 1)
. Put those all together and handle the escapes and you get what you see in the output of your type
command.
您嵌入的单引号没有被视为嵌入,它们终止了以前的字符串并启动了新的字符串。您的第一次尝试被视为tmux new -s $(pwd | tr
, \/
, ' ', \n
, 和的串联| tail -n 1)
。将所有这些放在一起并处理转义,您将得到您在type
命令输出中看到的内容。
Also worth considering: https://unix.stackexchange.com/questions/30925/in-bash-when-to-alias-when-to-script-and-when-to-write-a-function
也值得考虑:https: //unix.stackexchange.com/questions/30925/in-bash-when-to-alias-when-to-script-and-when-to-write-a-function