转义bash别名中的字符

Cha*_*nor 4 unix linux bash aliases .bash-profile

这是别名:

     # make a tmux session in working dir with the name of the dir
     alias th='tmux new -s $(pwd | tr '\/' '\n' | tail -n 1)'  
Run Code Online (Sandbox Code Playgroud)

由于转义字符或'别名内的单引号,它不起作用.打印出来

    $ type --all th
    th is aliased to `tmux new -s $(pwd | tr / n | tail -n 1)'
Run Code Online (Sandbox Code Playgroud)

看起来它只是剥离了'\.

我最终通过将单引号更改为双引号来修复它.

     # make a tmux session in working dir with the name of the dir
     alias th='tmux new -s $(pwd | tr "\/" "\n" | tail -n 1)'  
Run Code Online (Sandbox Code Playgroud)

我的问题是以前的工作怎么样?不应该bash抛出解析错误.

Cha*_*ffy 11

最好的建议:不要.

改为使用函数:

th() { tmux new -s "${PWD##*/}" "$@"; }
Run Code Online (Sandbox Code Playgroud)

${PWD##*/}是一个参数扩展,/从内容中删除所有内容,包括最后一个$PWD.


替代方法:文字行情

原始代码中的问题是它包含语法引号 - 由shell解析以确定单引号解析规则的开始和结束位置 - 在实际需要的地方是文字引号,被视为数据的地方(因此成为别名的一部分).

使这些引号文字的一种方法是使用$''引号形式,它允许你使用文字反斜杠来转义内部引号,使它们成为字面而不是语法:

alias th=$'tmux new -s $(pwd | tr \'\\\/\' \'\\n\' | tail -n 1)'
Run Code Online (Sandbox Code Playgroud)

请注意,在使用时$'',文字反斜杠也需要进行转义(因此,\\而不是写入\).


说明:为什么

POSIX shell语言中字符串的引用是逐个字符确定的.因此,在以下情况下:

'$foo'"$((1+1))"baz
Run Code Online (Sandbox Code Playgroud)

... $foo是单引号,因此被视为文字字符串,$((1+1))是双引号,因此有资格被视为算术扩展,并且baz不加引号 - 即使所有这三个连接形成单个单词($foo2baz).

这些引用都是语法 - 它们是shell的指令 - 不是文字(这意味着它们是该字符串计算的数据的一部分).


这适用于您以前的命令

alias th='tmux new -s $(pwd | tr '\/' '\n' | tail -n 1)'  
Run Code Online (Sandbox Code Playgroud)

... tr 结束单引号的参数中的单引号始于别名的开头.因此,\/并且\n在一个不带引号的上下文中进行评估(在其中\/变得公正/,\n变得公正n) - 并且因为,如上所述,多个不同引用的子串可以简单地连接成一个更大的字符串,您得到先前的命令,而不是别名.