> echo blablablaWANTEDTEXT[TEXTTOCOPY]blablabla... |
> awk -v searchtext=WANTEDTEXT '$0 ~ searchtext "\\[.*\\]" {
strstart=index($0,searchtext "[")+length(searchtext)+1;
tmpstr=substr($0,strstart); sub("].*$","",tmpstr); print tmpstr; } '
TEXTTOCOPY
Сperl
$ cat ip.txt
abc def ghi 123 345 456
abc def def ghi 123 345 456
abc def def def ghi 123 345 456 1234
$ perl -lane 'print join " ", grep { /def|123/ } @F' ip.txt
def 123
def def 123
def def def 123 1234
$ perl -lane 'print join " ", grep { $_ eq "def" || $_ eq "123" } @F' ip.txt
def 123
def def 123
def def def 123
-lane
здесь -l
удалит новую строку из строки ввода и добавит ее обратно, когда используется print
, -a
автоматически разделит строку ввода на пробелы и сохранит результаты в массиве @F
, -n
будет перебирать строки ввода но не будет автоматически печатать строки после обработки и -e
позволяет предоставить сценарий Perl из командной строки grep { /def|123/ } @F
будет фильтровать все элементы массива @F
, если они содержат def
или 123
grep { $_ eq "def" || $_ eq "123" } @F
print join " "
вывести элементы, полученные из вывода grep
с пробелом в качестве разделителя Вы можете использовать awk
и оставить только нужные поля:
echo -e "abc def bac 123\nabc def def bac 123\nabc def def def bac 123 123" \
| awk -v var1="def" -v var2="123" '{
i=0
for (j=1; j<=NF; j++){
if ($j==var1 || $j==var2){ $++i=$j }
if (i!=j){ $j="" }
}
print
}'
Это перебирает поля в цикле for -и переназначает def
или 123
следующему полю $++i=$j
(, начиная с индекса 0, поэтому первое поле равно 1, следующее — 2... )и сбрасывает текущее поле $j
в пустую строку ($j=""
), если индекс i
не является индексом цикла j
.
Выход:
def 123
def def 123
def def def 123 123
Использование ex
сawk
:
$ cat test.txt
abc def ghi 123 345 456
abc def def ghi 123 345 456
abc def def def ghi 123 345 456
$ printf '%s\n' 'g/^/.!awk -v ORS=" " -v RS=" " "/^(def|345)$/"' %p | ex test.txt
def 345
def def 345
def def def 345
$
Это:
ex
), где его можно изменить, распечатать и/или сохранить; awk
скрипт (отдельно ); %p
). Приведенная выше команда не сохраняет результаты обратно в файл. Если вы хотите сделать это, просто замените %p
на x
.
Подробное объяснение:
ex
— редактор файлов с поддержкой сценариев. Он принимает имя файла(test.txt
)в качестве аргумента и принимает команды редактирования со своего стандартного ввода.
Здесь мы предоставляем команды редактирования, используя printf
. Первый аргумент printf
— это строка форматирования, в данном случае '%s\n'
, которая используется для управления выводом остальных аргументов printf
. Мы говорим, что все аргументы будут строками, и после каждого должен быть напечатан символ новой строки. (Одинарные кавычки нужны для того, чтобы оболочка не интерпретировала обратную косую черту — мы хотим, чтобы printf
получал обратную косую черту, а не оболочка.)
Есть два аргумента, которые мы отправляем в ex
с помощью printf
. Вот они:
g/^/.!awk -v ORS=" " -v RS=" " "/^(def|345)$/"
%p
Второй из них самый простой. %
— диапазон адресов; это означает «весь буфер». p
— это команда печати.Так что это просто означает «распечатать весь буфер».
Первый требует некоторого разбора.
g/.../
— это «глобальная» команда. Он ищет во всем буфере строки, которые соответствуют заданному шаблону (, в данном случае ^
, регулярному выражению, означающему «начало строки» ), и запускает следующую ex
команду редактирования для каждой такой строки. Поскольку каждая строка имеет начало строки, каждая строка соответствует ^
, поэтому эффект заключается в выполнении следующей команды для каждой строки отдельно.
Тогда .
— это адрес, означающий «текущая строка (буфера )». Поскольку он указан после команды g
, он по очереди обращается к каждой строке буфера.
!
используется для запуска команды оболочки. Когда он имеет префикс адреса (, в данном случае .
), заданный диапазон строк (или одна строка )передается данной команде оболочки на стандартный ввод и результат (. ] стандартный вывод )команды помещается вместо этой строки буфера.
Другими словами, .!shell-command-here
в ex
означает фильтровать текущую строку буфера с помощью некоторой внешней команды.
Итак, мы рассмотрели, как эта настройка команды фильтрует каждую строку буфера (по отдельности )с помощью команды awk
; теперь давайте проанализируем эту команду awk
:
awk -v ORS=" " -v RS=" " "/^(def|345)$/"
Вы можете определить переменные для awk
, используя флаг -v
. Таким образом, первые несколько аргументов задают для переменных ORS
и RS
один пробел.
RS
в awk
— «разделитель записей»; по умолчанию его значением является новая строка. Какой бы символ он ни был установлен, awk
используется для разделения записей (обычно строк )по мере их считывания.
Точно так же ORS
, «разделитель выходных записей», управляет тем, что awk
использует для разделения записей (обычно строк )при их выводе на печать.
Установив каждый символ пробела,мы можем легко работать с каждым словом строки как с одной записью.
Следующая часть — это фактическая команда awk
.(awk
— это собственный язык сценариев.)awk
блоки команд состоят из условий и действий; любой из них может быть опущен. Здесь условие /.../
соответствует регулярному выражению, т. е. это условие применяется ко всем записям (слов, в данном случае ), которые соответствуют данному регулярному выражению. Частями регулярного выражения являются^
(начало строки ),$
(конец строки )и два возможных шаблона, сгруппированных в круглых скобках, разделенных вертикальной чертой|
(), чтобы указать, что любой из этих шаблонов является приемлемо.
Поскольку после условия (нет действия, действие будет заключено в фигурные скобки для awk
), действие awk по умолчанию "print" применяется к записям, соответствующим этому условию. (Помните, это означает, что awk
напечатает каждую совпадающую запись (слово )строки, а затем ex
прочитает этот вывод и поместит его вместо строки (s )буфера, который ex
передал в awk
в первую очередь.)
Это решение делает упрощающее предположение, что все шаблоны будут сопоставляться с полными словами, т. е. вы не захотите сопоставлять какие-либо шаблоны, которые включают пробелы. Это соответствует примеру ввода, который вы дали в вопросе.