awk 也可以对 shell 字符串(变量)使用字段标识符吗?

awk 也可以对 shell 字符串(变量)使用字段标识符吗?

嗯,按照我尝试的方式,这显然是不可能的。

这种替代方法可以获得酒吧不过,结果字符串有效:

#!/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 awk4.2 或更高版本中,如果值以 开头@/并以 结尾/,则将其视为正则表达式类型的变量)。

另一种方法是使用ARGVorENVIRON 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 -xawk 行后面的执行情况。您可以看到,执行时变量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")

相关内容