嗯,按照我尝试的方式,这显然是不可能的。
这种替代方法可以获得酒吧不过,结果字符串有效:
#!/bin/bash
path1=/usr/tmp/foo/bar/baz
awk -F/ '{print $5}' <<< "$path1"
到目前为止一切顺利,但是如果我不想使用<<<
操作员和那些臭名昭著的echo | ...
管道怎么办?简而言之,我想做的是将指令path1
作为变量传递-v pa="$path1"
和使用字段分隔符-F/
和字段标识符(例如$5
)来解析awk
-内部的 pa
变量,它的值是从外部的 path1
外壳变量。这awk
也可以在“内部”完成吗?
答案1
-v
选项或参数var=value
的问题awk
是它们不能用于任意数据,因为 ANSI C 转义序列(如\n
, \b
...)在其中扩展(并且在 GNU awk
4.2 或更高版本中,如果值以 开头@/
并以 结尾/
,则将其视为正则表达式类型的变量)。
另一种方法是使用ARGV
orENVIRON
awk
数组:
awk -F / 'BEGIN{$0 = ARGV[1]; print $5}' "$path1"
或者:
export path1
awk -F / 'BEGIN{$0 = ENVIRON["path1"]; print $5}'
或者:
path1="$path1" awk -F / 'BEGIN{$0 = ENVIRON["path1"]; print $5}'
现在,如果您想要的只是拆分 shell 变量,则可能不需要awk
.
在所有 POSIX shell 中:
IFS=/; set -f
set -- $path1
printf '%s\n' "$5"
答案2
你可以拆分pa
成一个数组
awk -F'/' -v pa=$path1 'BEGIN{split(pa, arr, FS); print(arr[5]); exit}'
答案3
有几种方法可以将环境变量传递到awk
脚本/命令中:
方法#1
这使得 shell$path1
在运行命令之前扩展变量awk
。
$ echo $path1
/usr/tmp/foo/bar/baz
$ awk -F'/' 'END{a="'$path1'"; split(a,arr,FS); print(arr[5])}' /dev/null
bar
方法#2
通过环境。变量 in 作为 awk 变量,a
.
$ awk -F '/' 'END{split(a,arr,FS); print(arr[5])}' a=$path1 /dev/null
bar
方法#3
使用开关显式传递awk
变量-v
。
$ awk -F'/' -v a=$path1 'END{split(a,arr,FS); print(arr[5])}' /dev/null
bar
调试
您可以在运行任何这些命令之前通过设置来启用 shell 的详细程度,set -x
以查看发生了什么。下面以方法 #2 为例:
$ set -x
$ awk -F '/' 'END{split(a,arr,FS); print(arr[5])}' a=$path1 /dev/null
+ awk -F / 'END{split(a,arr,FS); print(arr[5])}' a=/usr/tmp/foo/bar/baz /dev/null
bar
上面显示了set -x
awk 行后面的执行情况。您可以看到,执行时变量a
的值$path1
已在执行时扩展。
另一个例子,这次是方法#1:
$ awk -F'/' 'END{a="'$path1'";split(a,arr,FS); print(arr[5])}' /dev/null
+ awk -F/ 'END{a="/usr/tmp/foo/bar/baz";split(a,arr,FS); print(arr[5])}'
bar
在这里您可以看到 shell$path1
在执行之前肯定会扩展变量awk
。
答案4
怎么样:
basename "$(dirname "$path1")"
或者,如果您的 shell 支持进程替换并且您需要使用awk
:
awk -F'/' '{print $5}' <(printf '%s\n' "$path1")