Решение, аналогичное @ iñaki-murillo, но с использованием / proc / pid / cmdline
вместо ps
и grep
. Я также использую $ NF
и предполагаю, что последнее поле находится в формате pid / procname
, а не предполагаю, что это 7 долларов (на самом деле в моей системе это было 6 долларов).
netstat -putan|awk '/master/ {split($NF, pid,"/");sub(FS $NF,x);getline cmd < ("/proc/"pid[1]"/cmdline");print $0" "pid[1]"/"cmd}'
Объяснение
/ master /
Фильтр по строкам, содержащим master.
split ($ NF, pid, "/");
Разделить последнее поле на /
и сохранить в pid
sub (FS $ NF, x);
Удалить последнее поле.
getline cmd <("/ proc /" pid [1] "/ cmdline")
Прочтите вызов командной строки для рассматриваемого pid и сохраните его в cmd
.
print $ 0 "" pid [1] "/" cmd
Распечатать все
sed -e '
s/C/&/2;t # when 2nd C matches skip processing and print
/C/d # either one C or no C, so delete on C
'
sed -e '
/C/!b # no C, skip processing and print
/C.*C/!d # not(at least 2 C) => 1 C => delete
'
perl -lne 's/C/C/g == 1 or print'
Это удаляет строки, содержащие только одно вхождение C.
grep -v '^[^C]*C[^C]*$' file
Регулярное выражение [^C]
соответствует одному символу, который не является C (или новой строкой), и оператору повторения (также известному как Kleene звездочка) *
указывает ноль или более повторений предыдущего выражения.
По умолчанию вывод grep
(и большинства других текстовых инструментов) — стандартный вывод; перенаправить на новый файл и, возможно, переместить его поверх исходного файла, если вы этого хотите. То же самое регулярное выражение можно использовать с sed -i
для редактирования на месте:
sed -i '/^[^C]*C[^C]*$/d' file
(На некоторых платформах, особенно *BSD, включая macOS, параметр -i
требует аргумента, например -i ''
.)
В awk
вы можете установить любой разделитель полей. Если вы установите для него значение C
, то у вас будет столько полей +1, сколько вхождений C
.
Таким образом, если вы скажете awk -F'C' '{print NF}' <<< "C1C2C3"
, вы получите 4
: CCC
состоит из 3 C
s и, следовательно, 4 поля.
Вы хотите удалить строки, в которых C
встречается ровно один раз. Учитывая это, в вашем случае вы захотите удалить те строки, в которых ровно два C
-поля.Так что просто пропустите их:
$ awk -F'C' 'NF!=2' file
DTHGTY
HYTRHD
HTCCYD
Для тех, кто хочет конкретно awk
, я бы предложил
awk '/C[^C]*C/{next}//{print}'
пропустить строку, если она соответствует шаблону, иначе напечатать ее. На самом деле вам не нужно {print}
, вы можете использовать //
и печать по умолчанию, но я думаю, что это более понятно.
Моей первой мыслью было использовать egrep -v
с тем же шаблоном, но это на самом деле не отвечает на заданный вопрос.
sed подход:
sed -i '/^[^C]*C[^C]*$/d' input
-i
опция позволяет модифицировать файл на месте
/^[^C]*C[^C]*$/
— соответствует строкам, содержащим C
только один раз
d
- удалить совпадающие строки
Это можно сделать с помощью sed
как:
Код:
sed '/C.*C/p;/C/d' file1
Результаты:
DTHGTY
HYTRHD
HTCCYD
Как?
C
через /C.*C/p
C
через /C/d
, сюда входят строки, уже напечатанные на шаге 1 Инструмент POSIX для редактирования файла по сценарию (вместо того, чтобы печатать измененное содержимое в стандартный вывод) ex
.
printf '%s\n' 'g/^[^C]*C[^C]*$/d' x | ex file.txt
Конечно, вы можете использовать sed -i
, если ваша версия Sed поддерживает это, просто имейте в виду, что это не переносимо, если вы пишете скрипт, предназначенный для работы на разных типах систем. .
Дэвид Форстер спросил в комментариях:
Есть ли причина, по которой вы используете
printf
, а неecho
или что-то вродеex -c COMMAND
]?
Ответ: Да.
Для printf
и echo
это вопрос переносимости; см. Почему printf лучше, чем echo? Кроме того, легче вставлять символы новой строки между командами, используя printf
.
Для printf ... | ex
vs. ex -c ...
, это вопрос обработки ошибок.Для этой конкретной команды это не имеет значения, но в целом имеет значение; например, попробуйте поместить
ex -c '%s/this pattern is not in the file/replacement text/g | x' filename
в скрипт. В отличие от следующего:
printf '%s\n' '%s/no matching lines/replacement/g' x | ex file
Первый будет зависать и ждать ввода; второй завершится, когда команда ex
получит EOF, поэтому сценарий продолжится. Существуют альтернативные обходные пути, такие как s///e
, но они не указаны в POSIX. Я предпочитаю использовать портативную форму, показанную выше.
Для команды g
в конце должна быть новая строка, и я предпочитаю использовать printf
для переноса команд, а не вставлять новую строку в одинарные кавычки.
Вот несколько вариантов использования perl.
Поскольку вы сопоставляете только один символ, вы можете использовать tr/C//
(перевод без замены), чтобы вернуть количество совпадений C
:
perl -lne 'print if tr/C// != 1' file
В более общем случае, если вы хотите сопоставить многосимвольную строку или регулярное выражение, вы можете использовать это:
perl -lne 'print if (@m = /C/g) != 1' file
Это присваивает совпадения регулярного выражения /C/g
list @m
и выводит строки, если длина этого списка не равна 1
.
Переключатель -i
можно добавить для редактирования «на месте».