2016-06-20 4 views
1

Как найти разницу и разницу между двумя последовательными строками файла фиксированной ширины?найти, если две последовательные линии различны и где

пример файла:

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 

ответ

1

Вы можете использовать пустой разделитель полей, чтобы сделать каждый символ в поле в 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: Он будет работать только с версиями awk, которые разделяют записи на символы, когда FS имеет нулевое значение, например, GNU AWK, OSX AWK и т.д.

+1

спасибо, я изменил ваш сценарий в соответствии с моей потребностью (чтобы распечатать точную разницу). Работать хорошо! –

+1

вы можете заменить 'for (i = 1; i <= NF; i ++) a [i] = $ i' с' split ($ 0, a) ' – karakfa

+0

Спасибо @karakfa, очень хорошая идея. Сохраняет цикл, (отредактирован) – anubhava

2

Perl на помощь:

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

Это операцию XOR двух входных строк и отчетов все позиции, где результат не нулевой байт, т.е. там, где строки были разными.

+0

Короткий и мощный, спасибо. Я попробовал. –

+0

Он также должен быть довольно быстрым для длинных строк ввода. – choroba

1
$ 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 = "" 
Смежные вопросы