Как отфильтровать строки, имеющие 2 одинаковых значения?

Рассмотрим использование easy_install, возможно, в связи с виртуальной средой Python. Вам нужно установить пакет libzmq-dev, чтобы пакет Python компилировался.

sudo apt-get install libzmq-dev
virtualenv ~/test-ve
source ~/test-ve/bin/activate
easy_install pyzmq

Обратите внимание на отсутствие sudo для вызова easy_install, это связано с виртуальной средой Python. Однако вам нужно активировать virtualenv перед запуском кода Python. Для системной установки просто выполните

sudo apt-get install libzmq-dev
sudo easy_install pyzmq
5
задан 19 February 2018 в 15:24

9 ответов

Чтобы получить строки с одинаковым номером -> same_number pattern:

grep -E '([[:digit:]]+)[[:blank:]]+->[[:blank:]]+\1[[:blank:]]'
-E позволяет ERE (расширенное регулярное выражение) ([[:digit:]]+) соответствует одной или нескольким цифрам и помещается в захваченную группу 1 [[:blank:]]+ соответствует одному или нескольким горизонтальным пробелам -> соответствует буквально \1 относится к первой захваченной группе [[:blank:]], которая соответствует пробелу после этого

имеет

Чтобы получить строки, которые не имеют шаблона, добавьте только параметр -v:

grep -vE '([[:digit:]]+)[[:blank:]]+->[[:blank:]]+\1[[:blank:]]'

Пример:

% cat file.txt
[325194/777232]/var/cache/apt/srcpkgcache.bin:  100%  extents: 5 -> 1   [ OK ]
[325195/777232]/var/cache/apt/pkgcache.bin: 100%  extents: 4 -> 1   [ OK ]
[325255/777232]/var/cache/man/de/index.db:  100%  extents: 2 -> 2   [ OK ]
[325521/777232]/var/log/syslog: 100%  extents: 7 -> 1   [ OK ]
[325525/777232]/var/log/lastlog:    100%  extents: 2 -> 2   [ OK ]
[325531/777232]/var/log/syslog.1:   100%  extents: 5 -> 1   [ OK ]
[325572/777232]/var/log/kern.log:   100%  extents: 6 -> 1   [ OK ]
[325589/777232]/var/log/auth.log:   100%  extents: 3 -> 1   [ OK ]
[325621/777232]/var/log/faillog:    100%  extents: 2 -> 2   [ OK ]
[325625/777232]/var/log/wtmp:   100%  extents: 3 -> 1   [ OK ]
[325627/777232]/var/log/kern.log.1: 100%  extents: 2 -> 1   [ OK ]
[325644/777232]/var/log/cups/access_log.1:  100%  extents: 2 -> 1   [ OK ]
[325810/777232]/var/log/auth.log.1: 100%  extents: 2 -> 1   [ OK ]

% grep -E '([[:digit:]]+)[[:blank:]]+->[[:blank:]]+\1[[:blank:]]' file.txt
[325255/777232]/var/cache/man/de/index.db:  100%  extents: 2 -> 2   [ OK ]
[325525/777232]/var/log/lastlog:    100%  extents: 2 -> 2   [ OK ]
[325621/777232]/var/log/faillog:    100%  extents: 2 -> 2   [ OK ]

% grep -vE '([[:digit:]]+)[[:blank:]]+->[[:blank:]]+\1[[:blank:]]' file.txt
[325194/777232]/var/cache/apt/srcpkgcache.bin:  100%  extents: 5 -> 1   [ OK ]
[325195/777232]/var/cache/apt/pkgcache.bin: 100%  extents: 4 -> 1   [ OK ]
[325521/777232]/var/log/syslog: 100%  extents: 7 -> 1   [ OK ]
[325531/777232]/var/log/syslog.1:   100%  extents: 5 -> 1   [ OK ]
[325572/777232]/var/log/kern.log:   100%  extents: 6 -> 1   [ OK ]
[325589/777232]/var/log/auth.log:   100%  extents: 3 -> 1   [ OK ]
[325625/777232]/var/log/wtmp:   100%  extents: 3 -> 1   [ OK ]
[325627/777232]/var/log/kern.log.1: 100%  extents: 2 -> 1   [ OK ]
[325644/777232]/var/log/cups/access_log.1:  100%  extents: 2 -> 1   [ OK ]
[325810/777232]/var/log/auth.log.1: 100%  extents: 2 -> 1   [ OK ]
10
ответ дан 22 May 2018 в 13:01
  • 1
    Можно ли также использовать \s+ для пробелов или иначе? – Andrea Lazzarotto 19 February 2018 в 15:26
  • 2
    @AndreaLazzarotto \s на месте [[:blank:]] тоже будет работать. – heemayl 19 February 2018 в 15:31
  • 3
    Это сработало. Спасибо @heemayl. – vv0iadyk 19 February 2018 в 15:49
  • 4
    Есть ошибка: регулярное выражение также соответствует строкам, где первое число является префиксом второго (например, 4 -> 42). Добавление границы слова (или [[:blank:]]) в конце регулярного выражения исправит это. – nomadictype 20 February 2018 в 06:48
  • 5
    @nomadictype Хороший улов. Исправлена. – heemayl 20 February 2018 в 15:53

Чтобы получить строки с одинаковым номером -> same_number pattern:

grep -E '([[:digit:]]+)[[:blank:]]+->[[:blank:]]+\1[[:blank:]]' -E позволяет ERE (расширенное регулярное выражение) ([[:digit:]]+) соответствует одной или нескольким цифрам и помещается в захваченную группу 1 [[:blank:]]+ соответствует одному или нескольким горизонтальным пробелам -> соответствует буквально \1 относится к первой захваченной группе [[:blank:]], которая соответствует пробелу после этого

имеет

Чтобы получить строки, которые не имеют шаблона, добавьте только параметр -v:

grep -vE '([[:digit:]]+)[[:blank:]]+->[[:blank:]]+\1[[:blank:]]'

Пример:

% cat file.txt [325194/777232]/var/cache/apt/srcpkgcache.bin: 100% extents: 5 -> 1 [ OK ] [325195/777232]/var/cache/apt/pkgcache.bin: 100% extents: 4 -> 1 [ OK ] [325255/777232]/var/cache/man/de/index.db: 100% extents: 2 -> 2 [ OK ] [325521/777232]/var/log/syslog: 100% extents: 7 -> 1 [ OK ] [325525/777232]/var/log/lastlog: 100% extents: 2 -> 2 [ OK ] [325531/777232]/var/log/syslog.1: 100% extents: 5 -> 1 [ OK ] [325572/777232]/var/log/kern.log: 100% extents: 6 -> 1 [ OK ] [325589/777232]/var/log/auth.log: 100% extents: 3 -> 1 [ OK ] [325621/777232]/var/log/faillog: 100% extents: 2 -> 2 [ OK ] [325625/777232]/var/log/wtmp: 100% extents: 3 -> 1 [ OK ] [325627/777232]/var/log/kern.log.1: 100% extents: 2 -> 1 [ OK ] [325644/777232]/var/log/cups/access_log.1: 100% extents: 2 -> 1 [ OK ] [325810/777232]/var/log/auth.log.1: 100% extents: 2 -> 1 [ OK ] % grep -E '([[:digit:]]+)[[:blank:]]+->[[:blank:]]+\1[[:blank:]]' file.txt [325255/777232]/var/cache/man/de/index.db: 100% extents: 2 -> 2 [ OK ] [325525/777232]/var/log/lastlog: 100% extents: 2 -> 2 [ OK ] [325621/777232]/var/log/faillog: 100% extents: 2 -> 2 [ OK ] % grep -vE '([[:digit:]]+)[[:blank:]]+->[[:blank:]]+\1[[:blank:]]' file.txt [325194/777232]/var/cache/apt/srcpkgcache.bin: 100% extents: 5 -> 1 [ OK ] [325195/777232]/var/cache/apt/pkgcache.bin: 100% extents: 4 -> 1 [ OK ] [325521/777232]/var/log/syslog: 100% extents: 7 -> 1 [ OK ] [325531/777232]/var/log/syslog.1: 100% extents: 5 -> 1 [ OK ] [325572/777232]/var/log/kern.log: 100% extents: 6 -> 1 [ OK ] [325589/777232]/var/log/auth.log: 100% extents: 3 -> 1 [ OK ] [325625/777232]/var/log/wtmp: 100% extents: 3 -> 1 [ OK ] [325627/777232]/var/log/kern.log.1: 100% extents: 2 -> 1 [ OK ] [325644/777232]/var/log/cups/access_log.1: 100% extents: 2 -> 1 [ OK ] [325810/777232]/var/log/auth.log.1: 100% extents: 2 -> 1 [ OK ]
10
ответ дан 17 July 2018 в 20:30

Чтобы получить строки с одинаковым номером -> same_number pattern:

grep -E '([[:digit:]]+)[[:blank:]]+->[[:blank:]]+\1[[:blank:]]' -E позволяет ERE (расширенное регулярное выражение) ([[:digit:]]+) соответствует одной или нескольким цифрам и помещается в захваченную группу 1 [[:blank:]]+ соответствует одному или нескольким горизонтальным пробелам -> соответствует буквально \1 относится к первой захваченной группе [[:blank:]], которая соответствует пробелу после этого

имеет

Чтобы получить строки, которые не имеют шаблона, добавьте только параметр -v:

grep -vE '([[:digit:]]+)[[:blank:]]+->[[:blank:]]+\1[[:blank:]]'

Пример:

% cat file.txt [325194/777232]/var/cache/apt/srcpkgcache.bin: 100% extents: 5 -> 1 [ OK ] [325195/777232]/var/cache/apt/pkgcache.bin: 100% extents: 4 -> 1 [ OK ] [325255/777232]/var/cache/man/de/index.db: 100% extents: 2 -> 2 [ OK ] [325521/777232]/var/log/syslog: 100% extents: 7 -> 1 [ OK ] [325525/777232]/var/log/lastlog: 100% extents: 2 -> 2 [ OK ] [325531/777232]/var/log/syslog.1: 100% extents: 5 -> 1 [ OK ] [325572/777232]/var/log/kern.log: 100% extents: 6 -> 1 [ OK ] [325589/777232]/var/log/auth.log: 100% extents: 3 -> 1 [ OK ] [325621/777232]/var/log/faillog: 100% extents: 2 -> 2 [ OK ] [325625/777232]/var/log/wtmp: 100% extents: 3 -> 1 [ OK ] [325627/777232]/var/log/kern.log.1: 100% extents: 2 -> 1 [ OK ] [325644/777232]/var/log/cups/access_log.1: 100% extents: 2 -> 1 [ OK ] [325810/777232]/var/log/auth.log.1: 100% extents: 2 -> 1 [ OK ] % grep -E '([[:digit:]]+)[[:blank:]]+->[[:blank:]]+\1[[:blank:]]' file.txt [325255/777232]/var/cache/man/de/index.db: 100% extents: 2 -> 2 [ OK ] [325525/777232]/var/log/lastlog: 100% extents: 2 -> 2 [ OK ] [325621/777232]/var/log/faillog: 100% extents: 2 -> 2 [ OK ] % grep -vE '([[:digit:]]+)[[:blank:]]+->[[:blank:]]+\1[[:blank:]]' file.txt [325194/777232]/var/cache/apt/srcpkgcache.bin: 100% extents: 5 -> 1 [ OK ] [325195/777232]/var/cache/apt/pkgcache.bin: 100% extents: 4 -> 1 [ OK ] [325521/777232]/var/log/syslog: 100% extents: 7 -> 1 [ OK ] [325531/777232]/var/log/syslog.1: 100% extents: 5 -> 1 [ OK ] [325572/777232]/var/log/kern.log: 100% extents: 6 -> 1 [ OK ] [325589/777232]/var/log/auth.log: 100% extents: 3 -> 1 [ OK ] [325625/777232]/var/log/wtmp: 100% extents: 3 -> 1 [ OK ] [325627/777232]/var/log/kern.log.1: 100% extents: 2 -> 1 [ OK ] [325644/777232]/var/log/cups/access_log.1: 100% extents: 2 -> 1 [ OK ] [325810/777232]/var/log/auth.log.1: 100% extents: 2 -> 1 [ OK ]
10
ответ дан 23 July 2018 в 21:09

Вы можете сделать это с помощью GNU Awk (gawk).

Предполагая, что вход сохраняется в MY_FILE, и вы хотите видеть только строки с одинаковыми номерами, это может выглядеть так:

gawk '{match($0,/([[:digit:]]+)\s*->\s*([[:digit:]])+/,M);if(M[1]==M[2])print$0}' MY_FILE

Если вы хотите удалить строки с равными числами и показывать только те, у кого одинаковые числа , просто замените == на !=:

gawk '{match($0,/([[:digit:]]+)\s*->\s*([[:digit:]])+/,M);if(M[1]!=M[2])print$0}' MY_FILE

Пояснение: 6]

gawk будет выполнять инструкции внутри фигурных скобок для каждой строки, которые:

match($0, /([[:digit:]]+)\s*->\s*([[:digit:]])+/, M) ; 
if(M[1] == M[2]) print$0

Это означает, что соответствие регулярному выражению ([[:digit:]]+)\s*->\s*([[:digit:]])+ по всей строке ($0 ]) и сохраните совпадающий объект / массив в переменной M.

Затем сравните содержимое групп соответствия 1 и 2 (число до и после стрелки соответственно) и распечатайте всю строку, если это (если вы используете ==) или разные (если вы используете !=).

3
ответ дан 22 May 2018 в 13:01

Вам действительно не нужно сопоставление регулярных выражений, если ваши данные структурированы как поля с разделителями.

В вашем случае -> всегда отображается как 5-ое поле с разделителями пробелов, поэтому этого достаточно, чтобы проверьте значения 4-го и 6-го:

awk '$6 != $4' file

Если положение -> меняется, вы можете сделать что-то вроде

awk '{for(i=1;i<NF;i++) if ($i == "->" && $(i-1) != $(i+1)) {print; break}}' file

или разделить строку на ->, а затем разделите части с каждой стороны на пробелы и проверьте последнее поле первой части на первое поле второго:

awk -F' -> ' '{
  n=split($1,a,/[ \t]+/); split($2,b,/[ \t]+/); if(b[1] != a[n]) print
}' file
3
ответ дан 22 May 2018 в 13:01
  • 1
    Некоторые имена файлов будут содержать пробелы, поэтому положение - & gt; действительно меняется. Если awk смог начать с конца строки, это могло бы быть решением для случая. – vv0iadyk 27 February 2018 в 23:59

Вы можете сделать это с помощью GNU Awk (gawk).

Предполагая, что вход сохраняется в MY_FILE, и вы хотите видеть только строки с одинаковыми номерами, это может выглядеть так:

gawk '{match($0,/([[:digit:]]+)\s*->\s*([[:digit:]])+/,M);if(M[1]==M[2])print$0}' MY_FILE

Если вы хотите удалить строки с равными числами и показывать только те, у кого одинаковые числа , просто замените == на !=:

gawk '{match($0,/([[:digit:]]+)\s*->\s*([[:digit:]])+/,M);if(M[1]!=M[2])print$0}' MY_FILE

Пояснение:

gawk будет выполнять инструкции внутри фигурных скобок для каждой строки, которые:

match($0, /([[:digit:]]+)\s*->\s*([[:digit:]])+/, M) ; if(M[1] == M[2]) print$0

Это означает, что соответствие регулярному выражению ([[:digit:]]+)\s*->\s*([[:digit:]])+ по всей строке ($0 ]) и сохраните совпадающий объект / массив в переменной M.

Затем сравните содержимое групп соответствия 1 и 2 (число до и после стрелки соответственно) и распечатайте всю строку, если это (если вы используете ==) или разные (если вы используете !=).

3
ответ дан 17 July 2018 в 20:30

Вам действительно не нужно сопоставление регулярных выражений, если ваши данные структурированы как поля с разделителями.

В вашем случае -> всегда отображается как 5-ое поле с разделителями пробелов, поэтому этого достаточно, чтобы проверьте значения 4-го и 6-го:

awk '$6 != $4' file

Если положение -> меняется, вы можете сделать что-то вроде

awk '{for(i=1;i<NF;i++) if ($i == "->" && $(i-1) != $(i+1)) {print; break}}' file

или разделить строку на ->, а затем разделите части с каждой стороны на пробелы и проверьте последнее поле первой части на первое поле второго:

awk -F' -> ' '{ n=split($1,a,/[ \t]+/); split($2,b,/[ \t]+/); if(b[1] != a[n]) print }' file
3
ответ дан 17 July 2018 в 20:30

Вы можете сделать это с помощью GNU Awk (gawk).

Предполагая, что вход сохраняется в MY_FILE, и вы хотите видеть только строки с одинаковыми номерами, это может выглядеть так:

gawk '{match($0,/([[:digit:]]+)\s*->\s*([[:digit:]])+/,M);if(M[1]==M[2])print$0}' MY_FILE

Если вы хотите удалить строки с равными числами и показывать только те, у кого одинаковые числа , просто замените == на !=:

gawk '{match($0,/([[:digit:]]+)\s*->\s*([[:digit:]])+/,M);if(M[1]!=M[2])print$0}' MY_FILE

Пояснение:

gawk будет выполнять инструкции внутри фигурных скобок для каждой строки, которые:

match($0, /([[:digit:]]+)\s*->\s*([[:digit:]])+/, M) ; if(M[1] == M[2]) print$0

Это означает, что соответствие регулярному выражению ([[:digit:]]+)\s*->\s*([[:digit:]])+ по всей строке ($0 ]) и сохраните совпадающий объект / массив в переменной M.

Затем сравните содержимое групп соответствия 1 и 2 (число до и после стрелки соответственно) и распечатайте всю строку, если это (если вы используете ==) или разные (если вы используете !=).

3
ответ дан 23 July 2018 в 21:09

Вам действительно не нужно сопоставление регулярных выражений, если ваши данные структурированы как поля с разделителями.

В вашем случае -> всегда отображается как 5-ое поле с разделителями пробелов, поэтому этого достаточно, чтобы проверьте значения 4-го и 6-го:

awk '$6 != $4' file

Если положение -> меняется, вы можете сделать что-то вроде

awk '{for(i=1;i<NF;i++) if ($i == "->" && $(i-1) != $(i+1)) {print; break}}' file

или разделить строку на ->, а затем разделите части с каждой стороны на пробелы и проверьте последнее поле первой части на первое поле второго:

awk -F' -> ' '{ n=split($1,a,/[ \t]+/); split($2,b,/[ \t]+/); if(b[1] != a[n]) print }' file
3
ответ дан 23 July 2018 в 21:09
  • 1
    Некоторые имена файлов будут содержать пробелы, поэтому положение - & gt; действительно меняется. Если awk смог начать с конца строки, это могло бы быть решением для случая. – vv0iadyk 27 February 2018 в 23:59

Другие вопросы по тегам:

Похожие вопросы: