具有复杂 cmd、引号和 cmd 参数的 tcsh 别名

具有复杂 cmd、引号和 cmd 参数的 tcsh 别名

我绑定了一组管道命令的别名,浏览了这里的一些线程,发现 cmd 行应该以不同的方式使用。使用 !:1 而不是 $1 但它在以下上下文中似乎对我不起作用

这是我想要别名的一组命令(其计算中位数)

shell>  cat file_with_numbers| awk '{print $1}' | sort -n | awk ' { a[i++]=$1; } END { x=int((i+1)/2); if (x < (i+1)/2) print (a[x-1]+a[x])/2; else print a[x-1]; }'
shell> 1.15

我想将下面的部分别名为“中位数”

sort -n | awk ' { a[i++]=$1; } END { x=int((i+1)/2); if (x < (i+1)/2) print (a[x-1]+a[x])/2; else print a[x-1]; }'

所以我可以用

shell> cat file_with_numbers| awk '{print $1}' | median

alias median 'sort -n | awk ' { a[i++]=$1; } END { x=int((i+1)/2); if (x < (i+1)/2) print (a[x-1]+a[x])/2; else print a[x-1]; }''

() 的位置不好。 //单引号错误

alias median "sort -n | awk ' { a[i++]=$1; } END { x=int((i+1)/2); if (x < (i+1)/2) print (a[x-1]+a[x])/2; else print a[x-1]; }'"

cat file| awk '{print $5}'|  median
awk:  { a[i++]=; } END { x=int((i+1)/2); if (x < (i+1)/2) print (a[x-1]+a[x])/2; else print a[x-1]; }
awk:           ^ syntax error

所以我切换到\!:1并尝试了以下方法,但它仍然不起作用。我怎样才能正确地使用这个别名?

1> 试验1

alias median "sort -n | awk ' { a[i++]=\!:1; } END { x=int ( ( i+1 ) /2 ) ; if ( x < ( i+1 ) /2 ) print ( a[x-1]+a[x] ) /2 ; else print a[x-1] ; }' "


cat file|  awk '{print $5}' | median
Bad ! arg selector.

2> 审判2

alias median "sort -n | awk ' { a[i++]=\\!:1; } END { x=int ( ( i+1 ) /2 ) ; if ( x < ( i+1 ) /2 ) print ( a[x-1]+a[x] ) /2 ; else print a[x-1] ; }' "

cat file| awk '{print $5}' | median
awk:  { a[i++]=!:1; } END { x=int ( ( i+1 ) /2 ) ; if ( x < ( i+1 ) /2 ) print ( a[x-1]+a[x] ) /2 ; else print a[x-1] ; }
awk:            ^ syntax error

试用3>

答案1

您可以在别名中放置单行命令序列,但您可能需要到处添加反斜杠和单引号或双引号。但是,除非您需要使用 shell 历史记录中的参数或元素调用别名,或者需要最大限度地提高速度,否则有时将命令序列按原样放入文件中,将其标记为可执行文件,然后将其放置在您的文件中的某个位置会更容易。搜索路径($PATH$path)。

但要使以下内容成为别名:

sort -n | awk '{ a[i++]=$1; } END { x=int((i+1)/2); if (x < (i+1)/2) print (a[x-1]+a[x])/2; else print a[x-1]; }'

你需要确保

  • 管道运算符位于用引号引起来的字符串内;否则它将终止别名命令
  • the$要么位于用单引号括起来的字符串内,要么位于任何带引号的字符串之外且前面带有 a \(感谢 Stéphane,提供了替代方案)
  • 没有嵌套的单引号

不要用来\!:1尝试生产$1.\!:1如果您将参数传递给别名,则会使用它。你只是想让$1awk 看到文字。

在这种情况下,最安全的做法是用单引号将尽可能多的别名括起来,并且"仅用于包围文字单引号。您将看到下面出现两次"'"

ubuntu% alias median 'sort -n | awk '"'"'{ a[i++]=$1 ; } END { x=int ( ( i+1 ) /2 ) ; if ( x < ( i+1 ) /2 ) print ( a[x-1]+a[x] ) /2 ; else print a[x-1] ; }'"'"

ubuntu% seq 1 9 | median
5

答案2

除非你关心重新发明轮子,否则你也可以使用 GNU datamash

alias median 'datamash median 1'

datamash需要制表符分隔的列,尽管您可以使用 更改分隔符-t

对于您的特定问题,请注意$parameter(t)csh 中的扩展是在双引号内完成的,但与类似 Bourne 的 shell 相反,它不能用反斜杠禁用,因此您需要类似的内容:

alias median "sort -n | awk '{a[NR]="\$"1}; END {x = int(NR/2); print NR % 2 ? a[x+1] : (a[x]+a[x+1])/2}'"

也就是说,摆脱双引号来输入$as \$,或者采用 Mark 的方法并使用单引号,但摆脱双引号来输入文字单引号。

答案3

尝试这个:

$ alias median="sort -n|awk ' { a[i++]="\$1"; } END { x=int((i+1)/2); if (x < (i+1)/2) print (a[x-1]+a[x])/2; else print a[x-1]; }'"

$ cat file_with_numbers| awk '{print $1}'|median

相关内容