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

Я хочу, отфильтровывают строки, имеющие то же число-> то же число

из этого текста

    [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 ]
5
задан 19 February 2018 в 04:24

3 ответа

Для получения строк, что имеет same_number-> шаблон same_number :

grep -E '([[:digit:]]+)[[:blank:]]+->[[:blank:]]+\1[[:blank:]]'
  • -E включает ДО (Расширенное регулярное выражение)

  • ([[:digit:]]+) соответствия одна или несколько цифр и вставляет полученные соответствия группы 1

  • [[:blank:]]+ один или несколько горизонтальных пробелов

  • ->, соответствия буквально

  • \1 отсылают к первым полученным соответствиям группы

  • [[:blank:]] пробел после этого

, можно использовать подобную логику с другими популярными относящимися к обработке текстов инструментами/языками как sed, awk, perl.

Для получения строк, которые не имеют шаблон, только добавьте -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 November 2019 в 08:41

Можно сделать это с 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 November 2019 в 08:41

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

В Вашем случае, -> всегда появляется как 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 November 2019 в 08:41

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

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