简体   繁体   English

转义bash别名中的字符

[英]Escaping characters in bash alias

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 \\ . 看起来它只是剥离了'\\

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. 不应该bash抛出解析错误。

Best Advice: Don't. 最好的建议:不要。

Use a function instead: 改为使用函数:

th() { tmux new -s "${PWD##*/}" "$@"; }

${PWD##*/} is a parameter expansion which strips everything up to and including the last / from the contents of $PWD . ${PWD##*/}是一个参数扩展 ,它会删除所有内容,包括最后一个/来自$PWD的内容。


Alternate Approach: Literal Quotes 替代方法: 文字行情

The issue in your original code is that it contains syntactic quotes -- ones parsed by the shell to determine where single-quoted parsing rules begin and end -- in places where what you actually want is literal quotes, 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. POSIX shell语言中字符串的引用是逐个字符确定的。 Thus, in the case of: 因此,在以下情况下:

'$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 end the single quotes started at the beginning of the alias. ... tr的参数中的单引号结束了在别名开头处开始的单引号。 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. 因此, \\/\\n在一个不带引号的上下文中进行评估(其中\\/变为/ ,并且\\n变为n ) - 并且因为,如上所述,多个不同引用的子串可以被连接成一个更大的字符串,你得到你以前的命令,而不是别名。

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) . 您的第一次尝试被视为tmux new -s $(pwd | tr\\/ ,'', \\n| tail -n 1)的串联。 Put those all together and handle the escapes and you get what you see in the output of your type command. 把它们放在一起并处理转义,你就会得到你在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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM