Я также использовал сценарий для создания таких пользователей:
useradd -u 12345 -g users -d / home / username -s / bin / bash -p '$ (openssl passwd -1 Whirlpool_Sauna_Soap)' username
Вы были близки, но вам нужно было извлечь первое значение, потому что вы не хотите печатать его для каждого совпадающего слова. Мы можем использовать printf
, чтобы избежать новой строки.
awk '{printf "%s",$1
for (i=1;i<=NF;i++)
{
if ($i ~ /dog|cow/) { printf " %s",$i; }
}
print ""
}'
Результатом будет:
A dog999 dog284 cow284 cow432
B cow394 cow432 cow345 dog983
C dog847 cow395 dog496
D dog392 cow237 cow749
Его можно свернуть в одну строку:
awk '{printf "%s",$1; for (i=1;i<=NF;i++) { if ($i ~ /dog|cow/) { printf " %s",$i; } } print "" }'
Обратите внимание, что это напечатает строку, которая не соответствует ни одному слову , например,
E pig sheep
выведет
E
Если perl
решение подходит:
$ cat ip.txt
A dog999 dog284 cow284 pig383 pig234 cow432 chicken432
B cow394 cow432 cow345 dog983 pig345 chicken532
C dog847 pig357 pig236 cow395 dog496
D dog392 cow237 cow749
$ perl -lane 'print join("\t",$F[0],grep {/cow|dog/} @F[1..$#F])' ip.txt
A dog999 dog284 cow284 cow432
B cow394 cow432 cow345 dog983
C dog847 cow395 dog496
D dog392 cow237 cow749
-a
разделите строку ввода на пробелы и сохраните ее в @F
array -l
удалить символы новой строки из ввода и добавить обратно при печати join
добавит \ t
между элементами при печати $ F [0], grep {/ cow | dog /} @F [1 .. $ # F]
первый элемент массива и все элементы, соответствующие cow
или dog
perl -lape '$ _ = join "\ t", shift (@F), grep / cow | dog /, @ F'
. здесь shift
удалит и вернет первый элемент массива @F
, присвоение результата $ _
будет напечатано в конце любезно -p
вариант (Совет Стефану Шазеласу )
Если строки, не содержащие cow
или dog
, должны быть проигнорированы:
perl -lane 'print join("\t",$F[0],grep {//} @F[1..$#F]) if /cow|dog/' ip.txt
$ txr -e '(awk (:let tmp)
(:begin (set ofs "\t"))
(f (set tmp (pop f))
(ff (keep-if #/cow|dog/))
(push tmp f) (prn)))' data
A dog999 dog284 cow284 cow432
B cow394 cow432 cow345 dog983
C dog847 cow395 dog496
D dog392 cow237 cow749
Разбивка:
Пункт :let
в макросе определяет локальные переменные. Этот макрос реализует "парадигму Awk", но в безопасном для типов языке, в котором переменные должны быть определены перед использованием. Поэтому в дополнение к таким пунктам, как :begin
и :end
(аналогично BEGIN
и END
в POSIX Awk), этот Awk предоставляет :let
для определения переменных, лексически привязанных к макросу.
(f (set tmp (pop f)) ...)
- это условие-действие, где условием является f
. If - это список разграниченных полей из записи; если он не пуст (не равен nil
), то он ведет себя как булева истина. Поэтому формы действий выполняются, если в f
есть что-либо.
(set tmp (pop f))
берет первое поле из списка и сохраняет его во временной переменной tmp
. Второе поле становится первым, третье - вторым и так далее. Когда мы работаем с f
, запись rec
также восстанавливается автоматически с помощью ofs
, так же как в POSIX Awk запись $0
восстанавливается с помощью OFS
между полями.
(ff ...)
фильтрует поля с помощью операции, в данном случае (keep-if #/regex/)
. По сути, мы удаляем из f
все поля, которые не соответствуют регексу. ff
- это оператор, видимый внутри макроса awk
. keep-if
- регулярная функция; здесь она неявно куррируется, поэтому аргумент list не появляется. Она ожидает функцию-предикат, но regex является вызываемой функцией, поэтому подходит в качестве предиката.
Затем мы возвращаем сохраненное ранее первое поле в список полей f
с помощью (push tmp f)
.
(prn)
является эквивалентом print
. Без аргументов он печатает запись, за которой следует разделитель выходных записей (ors
), который инициализируется новой строкой. Поскольку rec
был восстановлен после всех манипуляций f
, мы получаем отфильтрованный вывод.
Как можно видеть, парадигма Awk в основном сохранилась, просто в контексте другого языка, в котором возможны разные вещи. Удобство простого выполнения $2 > $1
без проверки того, что эти поля действительно существуют, отсутствует; но с другой стороны, нам не нужно писать циклы для обработки полей как структуры данных. Поля могут быть отображены через функции или рассматриваться как стек.
Perl-решение Сундипа примерно переводится в awk
макросом следующим образом:
$ txr -e '(awk (t (prn `@[f 0]\t@{(keep-if #/cow|dog/ [f 1..:]) "\t"}`)))' data