![awk + 粘贴来清理路径?](https://linux22.com/image/32184/awk%20%2B%20%E2%80%8B%E2%80%8B%E7%B2%98%E8%B4%B4%E6%9D%A5%E6%B8%85%E7%90%86%E8%B7%AF%E5%BE%84%EF%BC%9F.png)
.cshrc
我在几台机器上的初始化文件中看到过这段代码。我经历了一些 awk 教程试图了解它是如何工作的,但我仍然无法解密它。
setenv PATH `echo $PATH | awk 'NF&&\\!x[$0]++' RS='[:|\n]' | paste -sd:`
它有什么作用?
答案1
反斜杠对我不起作用,但我可以向你解释一下:
echo "$PATH" | awk 'NF && !x[$0]++' RS='[:|\n]'
记录分隔符 ( RS
) 设置为字符“:”、“|”之一和换行符。$PATH
通常只是一行,元素之间用“:”分隔。这使得 awk 的行为就像路径不是用“:”分隔的,而是每个路径都在自己的行上。
NF
表示空行 ( NF == 0
) 被忽略。x
是一个以路径为下标的关联数组。表示如果大于 0,则!x[$0]++
忽略该“行”。结果是每行仅输出一次。x[$0]
在第一次运行期间x[$0]
增加,因此在接下来的运行中!x[$0]
为 false。
此示例显示处理最后一行后所有元素的频率:
echo "a:b:a:c:a:b" |
awk 'NF && !x[$0]++;END {for (var in x) print var ": " x[var]}' RS='[:|\n]'
a
b
c
a: 3
b: 2
c: 1
答案2
正如所描述的豪克这里的目的是$PATH
变量中只包含唯一的元素。
但这不是一个可移植的 awk 脚本,RS
通常仅限于单个字符而不是正则表达式。一个更便携的替代方案是这样的:
setenv PATH `printf "%s" "$PATH" | awk '{ sub("/$","") }; x[$0]++ < 1' RS=: | paste -s -d : -`
在 tcsh 中使用 gawk 和 nawk 进行测试。
有几点需要注意:
- 使用 可以避免无关的换行符
printf
。 - ,这
!
意味着历史扩展为 tcsh,可以通过检查值是否小于 1 来替换。 - 终止路径分隔符被删除
sub()
。