转义bash别名中的字符

时间:2017-03-22 13:50:46

标签: linux bash unix .bash-profile aliases

这是别名:

     # 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)'  

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

2 个答案:

答案 0 :(得分:10)

最佳建议:不要。

改为使用函数:

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

${PWD##*/}是一个parameter expansion,可以从/的内容中删除所有内容,包括最后$PWD

替代方法: Literal 引号

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

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

alias th=$'tmux new -s $(pwd | tr \'\\\/\' \'\\n\' | tail -n 1)'

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

说明:为什么

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

'$foo'"$((1+1))"baz

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

这些引用都是语法 - 它们是shell的指令 - 而不是 literal (这意味着它们将成为数据的一部分)字符串评估)。

这适用于您的上一个命令

alias th='tmux new -s $(pwd | tr '\/' '\n' | tail -n 1)'  

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

答案 1 :(得分:1)

您的嵌入式单引号未被视为嵌入式,它们会终止先前的字符串并盯着新字符串。您的第一次尝试被视为tmux new -s $(pwd | tr\/,'',\n| tail -n 1)的串联。把它们放在一起并处理转义,你得到你在type命令的输出中看到的内容。

还值得考虑:https://unix.stackexchange.com/questions/30925/in-bash-when-to-alias-when-to-script-and-when-to-write-a-function