【问题标题】:find if two consecutive lines are different and where查找两个连续的行是否不同以及在哪里
【发布时间】:2016-06-20 15:47:52
【问题描述】:

如何找到固定宽度文件的两个连续行之间的差异和差异点?

示例文件:

cat test.txt
1111111111111111122211111111111111
1111111111111111132211111111111111

输出:

它应该告诉用户两行之间存在差异,差异的位置在:第18个字符。(如上例)

如果它可以列出所有位置以防多种变化,那将非常有帮助。例如:

11111111111111111211113111
11111111111111111211114111

这里应该说:在第 18 位和第 26 位字符中发现了差异。

我正在尝试以下几行,但似乎迷路了。

while read line
do

echo $line |sed 's/./ &/g' |xargs -n1 #NOt able to apply diff (stupid try)

done <test.txt

【问题讨论】:

    标签: bash awk sed echo


    【解决方案1】:

    Perl 的救援:

    $ echo '11131111111111111211113111
    11111111111111111211114111' \
    | perl -le '$d = <> ^ <>;
                 print pos $d while $d =~ /[^\0]/g'
    4
    23
    

    它对两个输入字符串进行异或并报告结果不是空字节的所有位置,即字符串不同的位置。

    【讨论】:

    • 对于长输入字符串也应该很快。
    【解决方案2】:

    您可以使用空字段分隔符将每个字符设为awk 中的字段,并将每个偶数记录的条目与奇数记录进行比较:

    awk 'BEGIN{ FS="" } NR%2 {
      split($0, a)
      next
    }
    {
       print "line # ", NR
       for (i=1; i<=NF; i++)
          if ($i != a[i])
             print "difference spotted in position:", i
    }' test.txt
    
    line #  2
    difference spotted in position: 18
    line #  4
    difference spotted in position: 18
    difference spotted in position: 23
    

    输入数据在哪里:

    cat test.txt
    
    1111111111111111122211111111111111
    1111111111111111132211111111111111
    11111111111111111211113111
    11111111111111111311114111
    

    PS:它仅适用于FS 为空时将记录拆分为字符的awk 版本,例如GNU awk、OSX awk 等。

    【讨论】:

    • 谢谢,我根据需要修改了你的脚本(也打印出确切的差异)。工作得很好!!
    • 你可以用split($0,a)替换for (i=1; i&lt;=NF; i++) a[i] = $i
    • 你应该提到它只会在 awks 中工作,当 FS 为 NULL 时将记录拆分为字符(非 POSIX 行为,gawk 支持它 idk 关于其他 awks)和 idk 是否可能发生但如果第 1 行比第 2 行长,它不会发现差异。
    • 这就是为什么我没有说 gawk 特定的原因,因为我认为它可能在其他一些 awk 中也有这种行为,但它是 POSIX 未定义的行为。来自the POSIX specIf FS is a null string, the behavior is unspecified.
    • 是的,我同意你认为 POSIX awk 的行为可能会有所不同。我只是无法掌握纯 POSIX awk
    【解决方案3】:
    $ cat tst.awk
    { curr = $0 }
    (NR%2)==0 {
        currLgth = length(curr)
        prevLgth = length(prev)
        maxLgth = (currLgth > prevLgth ? currLgth : prevLgth)
        print "Comparing:"
        print prev
        print curr
        for (i=1; i<=maxLgth; i++) {
            prevChar = substr(prev,i,1)
            currChar = substr(curr,i,1)
            if ( prevChar != currChar ) {
                printf "Difference: char %d line %d = \"%s\", line %d = \"%s\"\n", i, NR-1, prevChar, NR, currChar
            }
        }
        print ""
    }
    { prev = curr }
    

    .

    $ cat file
    1111111111111111122211111111111111
    1111111111111111132211111111111111
    11111111111111111111111111
    11111111111111111111111
    
    $ awk -f tst.awk file
    Comparing:
    1111111111111111122211111111111111
    1111111111111111132211111111111111
    Difference: char 18 line 1 = "2", line 2 = "3"
    
    Comparing:
    11111111111111111111111111
    11111111111111111111111
    Difference: char 24 line 3 = "1", line 4 = ""
    Difference: char 25 line 3 = "1", line 4 = ""
    Difference: char 26 line 3 = "1", line 4 = ""
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-03-06
      • 1970-01-01
      • 2017-03-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多