问题描述
我正在使用 tcsh。我想将“cdup”别名为 cd
直到比参考目录低一级的目录。例如,如果我的参考目录是 /home/myself/support/bugs/,而我在 /home/myself/support/bugs/bug1/foo/bar,我希望 cdup
更改目录到 /home/myself/support/bugs/bug1.
我尝试了以下方法:
alias cdup 'cd `perl -e \'print $1 if $ENV{PWD} =~ m#\(/home/myself/support/bugs/[^/]+\)#\'`'
但我明白了:
无与伦比的`.
解决方法
有些引用是不必要的,†是什么让这更容易
alias cdup cd `perl -e'print $1 if $ENV{PWD} =~ m{(/home/user/support/bugs/[^/]+)}'`
或者你可以分解工作并避免引用问题
set d=`perl -e'print $1 if $ENV{PWD} =~ m{(...)}'`; alias cdup $d; unset d
它们在 tcsh
中的作用相同。
但是,如果 pwd
不在该“引用目录”中,那么别名最终是 cd
,这会将您带回主目录。这就是问题的提出方式——但这真的是我们想要的吗?
在上述第一种方法中解决此问题的一种方法是,如果我们位于引用层次结构之外,则将目录设置为当前目录本身
alias cdup cd `perl -e'$ENV{PWD} =~ m{(...)}; print $1 // $ENV{PWD}'`
这里的 //
是 defined-or operator。
或者在引用层次结构之外完全避免设置别名可能更合适,但这需要在tcsh
set d=`perl -e'print $ENV{PWD} =~ m{(...)}'`; if ($d != "") alias cdup cd $d ; unset d
由于在正则表达式中捕获 ()
,列表上下文中的匹配运算符(由 print
强加)返回其捕获或 undef
(如果不匹配),所以 shell 的变量$d
最终要么是捕获的值,要么是一个空字符串。
然后有条件地设置别名——所以如果没有匹配就没有cdup
。
† 来自 tcsh manual
别名 [姓名 [词表]]
不带参数,打印所有别名。使用 name,打印 name 的别名。使用name 和wordlist,指定wordlist 作为name 的别名。 wordlist 是命令和文件名替换。 name 不能是 'alias' 或 'unalias'。另请参阅unalias 内置命令。
注意没有提到引号,词表
不需要引号 ,因此根据 https://unix.stackexchange.com/questions/339328/creating-alias-for-cmd-with-backticks(感谢 brian d foy),答案是:
alias cdup 'cd `perl -e '\''print $1 if $ENV{PWD} =~ m#(/home/wittmann/support/bugs/[^/]+)#'\''`'
这完美地工作。感谢使用 ''' 在单引号字符串中引入单引号 (') 的技巧。
,这是一个没有外部命令的变体:
alias cdup cd /home/myself/support/bugs/\$PWD:s./home/myself/support/bugs/..:ah
它与原始行为的不同之处在于,如果在 reference directory 树之外使用,它会更改为 reference 目录,这可能是首选目录,也可能不是。 >