将“通配”语法限制为,特别是后缀通配,*
仅字符,假设我有:
// foo.txt
foo.*
biz
// bar.txt
bar
foo.bar
我想写:
diff <(sort -u foo) <(sort -u bar)
# alternatively
comm -3 <(sort -u foo) <(sort -u bar)
这样它就会返回:
# diff
> bar
< biz
# comm
bar
biz
这在本地可能吗?
答案1
如果您想报告 、inbar.txt
中不匹配任何模式的所有行,则可以是:foo.txt
zsh
unique_lines=(${(fu)"$(<bar.txt)"})
unique_patterns=(${(fu)"$(<foo.txt)"})
pattern="(${(j[|])unique_patterns})"
print -rC1 -- ${unique_lines:#$~pattern}
或者一口气完成:
print -rC1 -- ${${(fu)"$(<bar.txt)"}:#(${(j[|])~${(fu)"$(<foo.txt)"}})}
$(<file)
是类似 ksh 的运算符,它扩展到$file
尾随换行符的条纹内容。${(flags)param}
用途参数扩展标志来影响param
扩张。f
标志,按换行符分割(此处扩展到非空行列表)。u
(uniq):删除重复项。因此${(fu)"$(<foo.txt)"}
扩展到独特的非空行foo.txt
${array:#pattern}
$array
扩展到与模式不匹配的元素。这里的模式构造如下:${(j[|])unique_patterns}
其中 的元素$unique_patterns
与 相连接|
。所以我们最终得到了一个(line1|line2|...)
模式。- in
~
导致$~pattern
在变量扩展时将通配符视为此类。
请注意,通配符语法就是zsh
通配符的语法。这受到一些 shell 选项的影响,例如extendedglob
, kshglob
, nocasematch
...
在 中bash
,您可以执行类似的操作:
shopt -s extglob
pattern="@($(sort -u foo.txt | paste -sd '|' -))"
sort -u bar.txt |
while IFS= read -r line; do
[[ $line = $pattern ]] || printf '%s\n' "$line"
done
这次,语法是 bash extglob 通配符,类似于 ksh88 的语法。
请注意,行的顺序bar.txt
最终会改变。