比较 2 个数字并仅复制相似的部分 sed/grep/awk

Sam*_*ynn 5 bash scripts

假设我有一个名为a. 有一个阵列中的2项a[1]a[2]。所以每个元素包含一个数字值。这两个值都有相似的起始数字,但它们有不同的结尾。我将复制类似的部分并忽略其余部分。

所以作为一个例子

$ echo ${a[1]}
.1.3.6.1.4.1.232.13600256

$ echo ${a[2]}
.1.3.6.1.4.1.232.13600276
Run Code Online (Sandbox Code Playgroud)

我需要一些命令来比较这些元素,然后只复制相似的部分,直到第一个不匹配的字段。即,在这个例子中

输出

similar part is .1.3.6.1.4.1.232
Run Code Online (Sandbox Code Playgroud)

另一个例子

$ echo ${a[1]}
.1.3.6.1.4.1.759.2344.454545

$ echo ${a[2]}
.1.3.6.1.4.1.759.3234.454545
Run Code Online (Sandbox Code Playgroud)

此示例的输出

similar part is .1.3.6.1.4.1.759
Run Code Online (Sandbox Code Playgroud)

mur*_*uru 7

堆栈溢出

在 sed 中,假设字符串不包含任何换行符:

string1="test toast"
string2="test test"
printf "%s\n%s\n" "$string1" "$string2" | sed -e 'N;s/^\(.*\).*\n\1.*$/\1/'
Run Code Online (Sandbox Code Playgroud)

这假设字符串本身不包含换行符。

因此你可以这样做:

printf "%s\n" "${a[1]}" "${a[2]}" | sed -r 'N;s/^(.*)(\..*)?\n\1.*$/\1/'
Run Code Online (Sandbox Code Playgroud)

(\..*) 消除拖尾.从公共部分。


解决方案包括两部分:

  • 获取sed工作跨越两行。这是使用N,完成的,如果保证字符不在输入中,则可以避免。例如,因为给定的元素中不存在空格,我们可以改为使用:

    printf "%s " "${a[1]}" "${a[2]}" | sed -r 's/^(.*)(\..*)? \1.*$/\1/'
    
    Run Code Online (Sandbox Code Playgroud)

    本质上,分隔输出中两个元素的字符或字符串应该%sprintf格式化字符串之后使用,在\1正则表达式之前使用。

  • 使用正则表达式查找重复字符串。这个技巧是众所周知的,并且总是一个变体:

    (.*)\1
    
    Run Code Online (Sandbox Code Playgroud)

    .*匹配任何字符集,并将()它们分组以供以后参考,通过\1. 因此(.*)\1是任何跟随其自身的字符序列。