尊重全局字符的 Comm/Diff (或替代方案):这可能吗?

尊重全局字符的 Comm/Diff (或替代方案):这可能吗?

将“通配”语法限制为,特别是后缀通配,*仅字符,假设我有:

// 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.txtzsh

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最终会改变。

相关内容