awk 模式总是匹配最后一条记录?
Awk pattern always matches last record?
我正在从 zsh 切换到 bash,我需要生成一个 bash 脚本,它可以删除 $PATH
中的重复条目,而无需重新排序条目(因此没有 sort -d
魔法)。 zsh 有一些不错的数组处理快捷方式,可以轻松高效地执行此操作,但我不知道 bash 中有此类快捷方式。我遇到了 this answer ,这让我完成了 90% 的事情,但是有一个小问题我想更好地理解。看起来,当我 运行 那个 awk 命令时,最后处理的记录不正确地匹配模式。
$ awk 'BEGIN{RS=ORS=":"}!a[[=10=]]++' <<<"aa:bb:cc:aa:bb:cc"
aa:bb:cc:cc
$ awk 'BEGIN{RS=ORS=":"}!a[[=10=]]++' <<<"aa:bb:cc:aa:bb"
aa:bb:cc:bb
$ awk 'BEGIN{RS=ORS=":"}!a[[=10=]]++' <<<"aa:bb:cc:aa:bb:cc:" # note trailing colon
aa:bb:cc:
我不太了解 awk,不知道它为什么会这样,但我已经设法通过使用像这样的中间数组来解决这个问题。
array=($(awk 'BEGIN{RS=":";ORS=" "}!a[[=11=]]++' <<<"aa:bb:cc:aa:bb:cc:"))
# Use a subshell to avoid modifying $IFS in current context
echo $(export IFS=":"; echo "${array[*]}")
aa:bb:cc
然而,这似乎是一个次优解决方案,所以我的问题是:我是否在 awk 命令中做错了什么导致处理的最终记录出现误报匹配?
原始字符串中的最后一条记录是 cc\n
,与 cc
不同。当不确定任何语言的任何程序中发生了什么时,添加一些打印语句是 debugging/investigating:
的第 1 步
$ awk 'BEGIN{RS=ORS=":"} {print "<"[=10=]">"}' <<<"aa:bb:cc:aa:bb:cc"
<aa>:<bb>:<cc>:<aa>:<bb>:<cc
>:$
如果您希望 RS 为 :
或 \n
那么只需说明(至少使用 GNU awk):
$ awk 'BEGIN{RS="[:\n]"; ORS=":"} !a[[=11=]]++' <<<"aa:bb:cc:aa:bb:cc"
aa:bb:cc:$
以上的$
是我的提示
另一种可能的解决方法,而不是您的 bash 数组解决方案
$ echo "aa:bb:cc:aa:bb:cc" | tr ':' '\n' | awk '!a[[=10=]]++' | paste -sd:
aa:bb:cc
我正在从 zsh 切换到 bash,我需要生成一个 bash 脚本,它可以删除 $PATH
中的重复条目,而无需重新排序条目(因此没有 sort -d
魔法)。 zsh 有一些不错的数组处理快捷方式,可以轻松高效地执行此操作,但我不知道 bash 中有此类快捷方式。我遇到了 this answer ,这让我完成了 90% 的事情,但是有一个小问题我想更好地理解。看起来,当我 运行 那个 awk 命令时,最后处理的记录不正确地匹配模式。
$ awk 'BEGIN{RS=ORS=":"}!a[[=10=]]++' <<<"aa:bb:cc:aa:bb:cc"
aa:bb:cc:cc
$ awk 'BEGIN{RS=ORS=":"}!a[[=10=]]++' <<<"aa:bb:cc:aa:bb"
aa:bb:cc:bb
$ awk 'BEGIN{RS=ORS=":"}!a[[=10=]]++' <<<"aa:bb:cc:aa:bb:cc:" # note trailing colon
aa:bb:cc:
我不太了解 awk,不知道它为什么会这样,但我已经设法通过使用像这样的中间数组来解决这个问题。
array=($(awk 'BEGIN{RS=":";ORS=" "}!a[[=11=]]++' <<<"aa:bb:cc:aa:bb:cc:"))
# Use a subshell to avoid modifying $IFS in current context
echo $(export IFS=":"; echo "${array[*]}")
aa:bb:cc
然而,这似乎是一个次优解决方案,所以我的问题是:我是否在 awk 命令中做错了什么导致处理的最终记录出现误报匹配?
原始字符串中的最后一条记录是 cc\n
,与 cc
不同。当不确定任何语言的任何程序中发生了什么时,添加一些打印语句是 debugging/investigating:
$ awk 'BEGIN{RS=ORS=":"} {print "<"[=10=]">"}' <<<"aa:bb:cc:aa:bb:cc"
<aa>:<bb>:<cc>:<aa>:<bb>:<cc
>:$
如果您希望 RS 为 :
或 \n
那么只需说明(至少使用 GNU awk):
$ awk 'BEGIN{RS="[:\n]"; ORS=":"} !a[[=11=]]++' <<<"aa:bb:cc:aa:bb:cc"
aa:bb:cc:$
以上的$
是我的提示
另一种可能的解决方法,而不是您的 bash 数组解决方案
$ echo "aa:bb:cc:aa:bb:cc" | tr ':' '\n' | awk '!a[[=10=]]++' | paste -sd:
aa:bb:cc