Используя тот же подход, что и вы, используя временный файл, но делая его немного короче:
showqueue >/tmp/q.out; head -n 20 /tmp/q.out; echo '...'; tail -n 20 /tmp/q.out
Это не будет страдать от тех же проблем, которые обсуждались в другом ответе , но может отображать одни и те же строки дважды, если вывод был короче 40 строк.
Используемое вами регулярное выражение кажется слишком сложным, чтобы соответствовать только одному символу в середине, либо -
, .
, либо пробелу. Зачем вам [-.]?\s*?
. Это читается как :Совпадение с -
или .
(, опционально (`? ))с последующим пробелом (ну, действительно (из man pcrepattern):Символы \s по умолчанию теперь HT (9 ), LF (10 ), VT (11 ), FF (12 ), CR (13 )и пробел (32 )). Ну, собственно, несколько пробелов в ленивом режиме (*? ).
На мой взгляд, все, что нужно, это [.-]
просто, один символ, либо пробел, либо точка, либо тире. Это регулярное выражение:
(\d{5})[-. ](\d{6})
Лучше всего попробовать (единственный реальный способ выучить регулярные выражения )— зайти на regex101.com и попробовать. Здесь я создал пример этого поста подробно (в pcre, да ).
Вы видите, что в замену, о которой вы спрашиваете, я поставил эту замену:
(one:\1) (two:\2) (three:3)
И вы можете видеть, что в каждой строке все совпадение, от начала регулярного выражения до его конца, но не окружающий текст, заменяется этой строкой, где \1
и \2
преобразуются в захваченные значения. По одному на каждого (...)
.
Если вы хотите сделать первую (...)
незахватывающей, тогда будет только одна группа захвата, и замена должна измениться на:
(one:1) (two:\1) (three:3)
Только один \1
. В противном случае замена не удастся.
Если вы хотите заменить всю строку, сделайте так, чтобы она соответствовала всей строке от начала до конца:
^.*(?:\d{5})[-. ](\d{6}).*$
И сделайте замену только \1
, чтобы напечатать последнюю группу цифр.
Теперь о grep. У Grep нет замен, есть что-то, что помогает, но не является хорошим эквивалентом:\K
.
grep -Po '^.*\d{5}[-. ]\K\d{6}' file
Одна важная идея заключается в том, что -o
предназначен для выдачи всего, что соответствует регулярному выражению, да,все регулярное выражение, а не каждая совпадающая скобка.
Для работы с реальной заменой (или заменой(s///
))вам нужен sed
(, но он использует BRE, а не PCRE):
$ sed 's/^.*\([0-9]\{5\}\)[-. ]\([0-9]\{6\}\).*$/ \2 \1 /' file
567890 01234
222111 01111
543210 09876
, который выполняет реальную замену и позволяет изменить порядок (или повторить ).
Если вы хотите grep
выделить только фрагменты строк, где последние 6 символов являются цифрами, просто скажите, что
grep -Po "\d{6}$" file
Добавьте внешний вид, если вы хотите быть уверенным в разделителе
grep -Po "(?<=[-. ])\d{6}$" file
Или, если количество цифр неопределенно
grep -Po "\d+$" file
Просто привяжите к концу строки и сопоставьте в обоих случаях.
Я считаю, что лучший план — это Обычно не иметь дело с теми частями, с которыми вам не нужно иметь дело, (хотя есть все добродетели в том, чтобы делать что-то трудным путем, чтобы учиться....так держать ;D ).
Захват не влияет на то, что grep считает совпавшими частями при использовании опции -o
или --only-matching
. Все не захватывающие -средства заключаются в том, что вы не собираетесь считать группу одной из доступных обратных ссылок (или замен в контекстах, где замена является опцией ).
Например:
$ printf 'aba\nabb\nabc\n' | grep -Po '(a)(b)'
ab
ab
ab
$ printf 'aba\nabb\nabc\n' | grep -Po '(a)(b)\1'
aba
$ printf 'aba\nabb\nabc\n' | grep -Po '(?:a)(b)\1'
abb
Вероятно, то, что вы ищете в этом контексте, является либо утверждением просмотра назад нулевой длины:
printf 'aba\nabb\nabc\n' | grep -Po '(?<=a)b'
b
b
b
или утверждение \K
"держаться левой стороны"
$ printf 'aba\nabb\nabc\n' | grep -Po 'a\Kb'
b
b
b
(последний немного более гибкий, так как допускает сопоставление переменной длины ).
Так например
$ grep -Po '\d{5}[-.]?\s*\K\d{6}' file
567890
222111
543210