Команда AWK и команда SED

Linux

В дни сверхурочной работы поторопитесь и изучите вау🤩

зачем использовать

Для нашего обслуживающего персонала нам часто нужно обращаться к серверу, чтобы найти информацию журнала, проверить подробную информацию об ошибках или контролировать сервер.Мощные инструменты, такие как grep, уже могут удовлетворить большинство потребностей, но два мощных командных инструмента, awk и sed, также очень полезно. Следующие записи о том, как использовать эти два инструмента.


AWK

Цитата из Википедии:

AWK - это отличный инструмент обработки текста и одним из самых мощных двигателей обработки данных, доступных в средах Linux и Unix. Максимальные возможности языка манипуляций программирования и данных (названные в честь инициалов его основателей Альфред Айроу, Питер Вайнберг и Брайан Коллингем) зависят от того, что человек обладает знанием. Новая версия Nawk Gawk, созданная awk, была улучшена. Теперь GAWK используется ежедневно по умолчанию под Linux System. Вы можете использовать команду для просмотра источника AWK, который применяется (LS -L / bin / awk)


начать использовать

Сначала запросите фрагмент сетевых данных и сохраните его с помощью перенаправления:

$ netstat -ano > netstat.txt
$ awk '{print}' netstat.txt
Proto Recv-Q Send-Q Local Address           Foreign Address         State       Timer
tcp        0      0 0.0.0.0:8009            0.0.0.0:*               LISTEN      off (0.00/0/0)
tcp        0      0 0.0.0.0:18090           0.0.0.0:*               LISTEN      off (0.00/0/0)
tcp        0      0 0.0.0.0:41999           0.0.0.0:*               LISTEN      off (0.00/0/0)
tcp        0      0 0.0.0.0:8080            0.0.0.0:*               LISTEN      off (0.00/0/0)
tcp        0      0 0.0.0.0:42801           0.0.0.0:*               LISTEN      off (0.00/0/0)
tcp        0      0 0.0.0.0:42869           0.0.0.0:*               LISTEN      off (0.00/0/0)
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      off (0.00/0/0)
tcp        0      0 0.0.0.0:10050           0.0.0.0:*               LISTEN      off (0.00/0/0)
tcp        0      0 127.0.0.1:8005          0.0.0.0:*               LISTEN      off (0.00/0/0)
tcp        0      0.0.0.0:10050        192.168.120.1:7569      TIME_WAIT   timewait (27.08/0/0)

Простой в использовании, выходные столбцы 1 и 4:

  • Оператор awk, заключенный в фигурные скобки в одинарные кавычки, является оператором awk.Обратите внимание, что он может содержаться только в одинарных кавычках.
  • один из них1....n представляет количество столбцов. ($0 означает всю строку)
$ awk '{print $1,  $4}' netstat.txt
Proto Local
tcp 0.0.0.0:8009
tcp 0.0.0.0:18090
tcp 0.0.0.0:41999
tcp 0.0.0.0:8080
tcp 0.0.0.0:42801
tcp 0.0.0.0:42869
tcp 0.0.0.0:22
tcp 0.0.0.0:10050
tcp 127.0.0.1:8005

Awk может форматировать вывод, и те, кто использовал такие языки, как C и Java, должны быть знакомы с:

$ awk '{printf "%-8s %-8s %-8s %-18s %-22s %-15s\n",$1,$2,$3,$4,$5,$6}' netstat.txt
Proto    Recv-Q   Send-Q   Local              Address                Foreign
tcp      0        0        0.0.0.0:8009       0.0.0.0:*              LISTEN
tcp      0        0        0.0.0.0:18090      0.0.0.0:*              LISTEN
tcp      0        0        0.0.0.0:41999      0.0.0.0:*              LISTEN
tcp      0        0        0.0.0.0:8080       0.0.0.0:*              LISTEN

фильтровать записи

Одно или несколько полей могут быть оценены с помощью судьи сравнения (связаны или нет)

Сравнительные тестеры: ==, !=, >=, >=, >,

Например, чтобы отфильтровать строки данных, третий столбец которых больше 0:

$ awk '$3 > 0 {print }' netstat.txt
Proto Recv-Q Send-Q Local Address           Foreign Address         State       Timer
tcp        0     48 10.96.0.33:22           0.0.0.0:42280       ESTABLISHED on (0.20/0/0)

Если вам нужно вывести номер строки, вы можете использовать встроенную переменную NR:

$ awk '$3 > 0 {print NR, $0 }' netstat.txt
1 Proto Recv-Q Send-Q Local Address           Foreign Address         State       Timer
23 tcp        0         0.0.0.0:22            0.0.0.0:42280     ESTABLISHED on (0.20/0/0)

встроенная переменная

Встроенные переменные эквивалентны встроенным переменным программы и могут быть использованы непосредственно:

Переменная Значение переменной
$0 Текущая запись (эта переменная хранит содержимое текущей строки
1~n N-е поле текущей записи, поля разделены разделителем FS
FS Разделитель полей ввода, по умолчанию пробел или табуляция
NF Количество полей в текущей записи — это количество столбцов.
NR Количество записей, которые были прочитаны, - это номер строки, начиная с 1. Если есть несколько файлов, это значение также постоянно накоплено.
FNR Текущее количество записей и отличия NR состоит в том, что это значение является их собственным номером файловой строки
RS разделитель входных записей, по умолчанию новая строка
OFS Разделитель полей вывода, по умолчанию также пробел
ORS Разделитель выходных записей, по умолчанию — новая строка
FILENAME Имя текущего входного файла

Например, разделителем одних файлов является не пробел, а других, разделитель можно настроить:

$ awk 'BEGIN{FS=":"} {print $1, $3, $6}' /etc/passwd
nobody -2 /var/empty
root 0 /var/root

Вышеупомянутая команда эквивалентна: (- F, означает формулировать разделители)

$ awk -F: '{print $1, $3, $6}' /etc/passwd

Примечание. Если вы хотите разработать несколько разделителей, вы можете использовать:

awk -F '[;:]'

Разделитель для настраиваемых полей вывода (например, вкладка \t):

$ awk 'BEGIN{FS=":"} {print $1, $3, $6}' OFS="\t" /etc/passwd
nobody	-2	/var/empty
root	0	/var/root
daemon	1	/var/root

совпадение строки

Вы можете сопоставлять связанные символы, такие как grep:

$ awk '/LISTEN|WAIT/' netstat.txt
tcp        0      0 0.0.0.0:8009            0.0.0.0:*               LISTEN      off (0.00/0/0)
tcp        0      0 0.0.0.0:18090           0.0.0.0:*               LISTEN      off (0.00/0/0)
tcp        0      0 0.0.0.0:41999           0.0.0.0:*               LISTEN      off (0.00/0/0)
tcp        0      0 0.0.0.0:8080            0.0.0.0:*               LISTEN      off (0.00/0/0)
tcp        0      0 0.0.0.0:42801           0.0.0.0:*               LISTEN      off (0.00/0/0)
tcp        0      0 0.0.0.0:42869           0.0.0.0:*               LISTEN      off (0.00/0/0)
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      off (0.00/0/0)
tcp        0      0 0.0.0.0:10050           0.0.0.0:*               LISTEN      off (0.00/0/0)
tcp        0      0 127.0.0.1:8005          0.0.0.0:*               LISTEN      off (0.00/0/0)
tcp        0      0 0.0.0.0:10050           0.0.0.0:7569      TIME_WAIT   timewait (27.08/0/0)

Вы также можете точно сопоставить поле:

$ awk '$6 ~/LISTEN|CLOSE/ {print $0}' netstat.txt
tcp        0      0 0.0.0.0:8009            0.0.0.0:*               LISTEN      off (0.00/0/0)
tcp        0      0 0.0.0.0:18090           0.0.0.0:*               LISTEN      off (0.00/0/0)
tcp        0      0 0.0.0.0:41999           0.0.0.0:*               LISTEN      off (0.00/0/0)
tcp        0      0 0.0.0.0:8080            0.0.0.0:*               LISTEN      off (0.00/0/0)
tcp        0      0 0.0.0.0:42801           0.0.0.0:*               LISTEN      off (0.00/0/0)
tcp        0      0 0.0.0.0:42869           0.0.0.0:*               LISTEN      off (0.00/0/0)
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      off (0.00/0/0)
tcp        0      0 0.0.0.0:10050           0.0.0.0:*               LISTEN      off (0.00/0/0)
tcp        0      0 127.0.0.1:8005          0.0.0.0:*               LISTEN      off (0.00/0/0)
tcp        1      0 0.0.0.0:44690           0.0.0.0:80            CLOSE_WAIT  off (0.00/0/0)
tcp6       0      0 :::27777                :::*                    LISTEN      off (0.00/0/0)
tcp6       0      0 :::10050                :::*                    LISTEN      off (0.00/0/0)

Среди них: ~ указывает на начало шаблона, а два / в середине — шаблоны, которые эквивалентны сопоставлению регулярных выражений (по той же причине, используйте перед регулярными выражениями! Можно обратить, что здесь не будет показано)


разделить файл

Укажите столбец в качестве классификатора и используйте перенаправление для экспорта в разные файлы.Например, следующий оператор разделяется по шестому столбцу:

$ awk 'NR!=1 {print > $6}' netstat.txt
$ ls
ESTABLISHED          TIME_WAIT            netstat.txt          test.txt     CLOSE_WAIT           LISTEN               off

Вы можете просмотреть ваши файлы и обнаружили, что это уже результат классификации:

$ cat ESTABLISHED
tcp        0      0 0.0.0.0:38440        0.0.0.0:20880       ESTABLISHED keepalive (5806.94/0/0)
tcp        0      0 0.0.0.0:58814        0.0.0.0:20880        ESTABLISHED keepalive (5872.47/0/0)
tcp        0      0 0.0.0.0:49998        0.0.0.0:80        ESTABLISHED off (0.00/0/0)
tcp        0      0.0.0.03:22            0.0.0.02:42280    ESTABLISHED on (0.20/0/0)
tcp        0      0 0.0.0.0:56146        0.0.0.0:20892    ESTABLISHED keepalive (2661.21/0/0)

Кроме того, вы можете указать определенные столбцы для вывода или использовать сложные выражения (например, операторы if-else-if, awk — это интерпретатор сценариев)

$ awk 'NR!=1{if($6 ~ /TIME|ESTABLISHED/) print > "1.txt";
else if($6 ~ /LISTEN/) print > "2.txt";
else print > "3.txt" }' netstat.txt
$ ls *.txt
1.txt       2.txt       3.txt       netstat.txt

Обратите внимание, что оператор if-else должен находиться в тех же фигурных скобках {}~


статистика

Следующий оператор используется для подсчета общего размера файлов с суффиксом .txt:

$ ll *.txt | awk '{sum+=$5} END {print sum}'
769.9

Точно так же вы можете использовать данные по статистике, отдельной статистики различных элементов.

Используется для подсчета состояния сети

$ awk 'NR!=1{a[$6]+=1} END {for (i in a) print i ", " a[i];}' netstat.txt
LISTEN, 11
CLOSE_WAIT, 1
TIME_WAIT, 26
off, 7
ESTABLISHED, 10

Используется для подсчета объема памяти, занимаемого каждым пользовательским процессом: (просматривается с помощью ps -aux, в шестом столбце указывается занимаемая память)

$ ps -aux | awk 'NR!=1{a[$1]+=$6} END {for (i in a) print i ", " a[i]"kb";}'
apache, 156952kb
dbus, 1236kb
polkitd, 8252kb
named, 104220kb
libstor+, 148kb
mysql, 106304kb
root, 325464kb

awk-скрипт

Есть два ключевых слова, на которые следует обратить внимание: BEGIN и END.:

  • BEGIN {это оператор перед выполнением}
  • END{Это оператор после выполнения}
  • {вот инструкция, которая будет выполняться при обработке каждой строки}

Например, в следующем примере просто подсчитайте количество строк: (Просто краткое введение в то, как писать скрипты, небольшие партнеры могут изучить дополнительные настройки~)

$ vim cal.awk
#! /bin/awk -f
# 运行前
BEGIN {
    lineNumber = 0
    print "开始执行"
}
# 运行中
{
    lineNumber += 1
    printf "当前行号 %s, 数据为 %s \n", lineNumber, $0

}
# 运行后
END {
    print "结束"
}

Выполните скрипт (вы также можете использовать ./cal.awk netstat.txt)

$ awk -f cal.awk netstat.txt
awk -f cal.awk netstat.txt
开始执行
当前行号 1, 数据为 Proto Recv-Q Send-Q Local Address           Foreign Address         State       Timer
当前行号 2, 数据为 tcp        0      0 0.0.0.0:8009            0.0.0.0:*               LISTEN      off (0.00/0/0)
当前行号 3, 数据为 tcp        0      0 0.0.0.0:18090           0.0.0.0:*               LISTEN      off (0.00/0/0)
当前行号 4, 数据为 tcp        0      0 0.0.0.0:41999           0.0.0.0:*               LISTEN      off (0.00/0/0)
当前行号 5, 数据为 tcp        0      0 0.0.0.0:8080            0.0.0.0:*               LISTEN      off (0.00/0/0)
当前行号 6, 数据为 tcp        0      0 0.0.0.0:42801           0.0.0.0:*               LISTEN      off (0.00/0/0)
当前行号 7, 数据为 tcp        0      0 0.0.0.0:42869           0.0.0.0:*               LISTEN      off (0.00/0/0)
结束

Объединить переменные среды

Работайте с переменными окружения, используя параметр -v с ENVIRON:

$ echo $x
0
$ echo ${test}
LISTEN
$ awk -v val=${x} '$2==val || $6==ENVIRON["test"] { print $1, $2, $3}' netstat.txt
tcp 0 0
tcp 0 0
tcp 0 0
tcp 0 0
tcp 0 0

Конечно, при использовании переменных среды не забудьте экспортировать переменные


команда СЭД

Полное название: Stream EDitor, функция похожа на awk, разница в том, что sed проще awk и часто используется для замены символов. Сопоставители могут быть сопоставлены с использованием регулярных выражений, поэтому, если вы хотите использовать более мощные функции, вам нужно понимать регулярные выражения~


Используйте команду S для замены

Тест со следующим текстом

$ cat self.txt
First line
    My name is John
Second line
    I like milk
Third line
    I like basketball
Four line
    I live in china

Введение в команду S:

s означает команду замены, /I/ означает совпадение I, /John/ означает замену предыдущего I на Json, /g означает совпадение всех символов во всех строках (обратите внимание, что совпадение чувствительно к регистру)

$ sed "s/I/John/g" self.txt
First line
    My name is John
Second line
    John like milk
Third line
    John like basketball
Four line
    John live in china

Это только заменяет символы выходного потока, а данные исходного текста не изменятся.Есть два способа изменить данные выходного потока:

  • Использовать перенаправление >
$ sed "s/I/John/g" self.txt > other.txt
  • Используйте параметр -i
$ sed -i "s/I/John/g" self.txt

Вы можете добавлять данные в начале каждой строки: (например, добавить символ # в начале текста)

$ sed "s/^/#/g" self.txt
sed "s/^/#/g" self.txt
#First line
#    My name is John
#Second line
#    I like milk
#Third line
#    I like basketball
#Four line
#    I live in china

Вы можете добавить некоторые данные в конце строки: (например, добавить разделитель или терминатор)

$ sed "s/$/---/g" self.txt
First line---
    My name is John---
Second line---
    I like milk---
Third line---
    I like basketball---
Four line---
    I live in china---

Используйте регулярные выражения для удаления тегов в html:

HTML-текст:

<b>This is</b><p> a test file</p><span style="text-decoration: underline;"> @John hahah</span>

Заменить скрипт:

# 熟悉正则表达式的小伙伴应该不陌生
# 使用[^>]表示除了>之外的字符,*号表示任意个字符
$ sed "s/<[^>]*>//g" html.txt
This is a test file @John hahah

Вы можете указать текст для замены определенного номера строки и использовать запятые (,) для соединения нескольких строк: (например, следующее заменяет только данные в строках с 5 по 8)

$ sed "5,8s/I/John/g" self.txt
First line
    My name is John
Second line
    I like milk             #这行的I没有被替换
Third line
    John like basketball     #替换了
Four line
    John live in china       #替换了

Тестовый текст:

$ cat 1.txt
This is first line.
This is second line.
This is third line.
This is four line.

Указывает заменить только первое вхождение символа в каждой строке:

$ sed "s/s/S/1" 1.txt
ThiS is first line.
ThiS is second line.
ThiS is third line.
ThiS is four line.

Указывает заменить второй и последующие символы каждой строки:

$ sed "s/s/S/2g" 1.txt
This iS firSt line.
This iS Second line.
This iS third line.
This iS four line.

несколько совпадений

Если вам нужно сопоставить несколько шаблонов в одной команде, вы можете написать несколько совпадающих выражений, разделенных точкой с запятой; (например, замените This на That в строках 1 и 2, а is в строках 3 и до последней замените на are ).

$ sed '1,2s/This/That/g; 3,$s/is/are/g' 1.txt
That is first line.
That is second line.
Thare are third line.   #没想到将This的is也替换成are了=-=
Thare are four line.    #可以修改sed '1,2s/This/That/g; 3,$s/is/are/2' 1.txt, 指定替换第二个字符is

Вы можете использовать & для использования в качестве переменной для сопоставления, а затем добавить некоторый контент до и после сопоставленной переменной:

$ sed 's/line/front [&] end/g' 1.txt
This is first front [line] end.
This is second front [line] end.
This is third front [line] end.
This is four front [line] end.

скобки совпадают

Строка, совпадающая с регулярным выражением, заключенная в круглые скобки, может использоваться как переменная, где \1 означает первое совпадение, \2 означает второе совпадение и т. д.)

$sed 's/^This is \([A-Za-z]*\) line.$/\1/g' 1.txt
first
second
third
four

Регулярные выражения широки и глубоки, и каждый раз требуется время, чтобы их изучить!


N-команда

Эта команда отправит содержимое следующей строки в буфер, и две строки будут сопоставлены в одной строке: (Например, в следующей команде после объединения двух строк в одну символ новой строки \n между двумя строками заменяется пробелом, поэтому в результате вывода исходная четная строка и нечетная строка объединяются)

$ sed 'N;s/\n/ /g' self.txt
First line     My name is John
Second line     I like milk
Third line     I like basketball
Four line     I live in china

команда и я команда

A: означает добавление, добавление после линии:

$ sed '$ a --- the end ---' 1.txt
This is first line.
This is second line.
This is third line.
This is four line.
--- the end ---

i: означает вставить, вставить перед строкой:

$ sed '1 i --- the start ---' 1.txt
--- the start ---
This is first line.
This is second line.
This is third line.
This is four line.

Вы можете выполнить сопоставление, а затем добавить или вставить данные перед совпадающей строкой:

$ sed '/line/a  I find a line' 1.txt
This is first line.
I find a line
This is second line.
I find a line
This is third line.
I find a line
This is four line.
I find a line

команда с

Команда C: заменить команду, заменить совпадающую строку

Замена в одну строку:

$ sed '2 c You have been replaced' 1.txt
This is first line.
You have been replaced
This is third line.
This is four line.

Многострочная замена

$ sed '2,$ c You have been replaced' 1.txt
This is first line.
You have been replaced

Альтернативный или соответствующий ряд:

$ sed '/This is/c You have been replaced' 1.txt
You have been replaced
You have been replaced
You have been replaced
You have been replaced

D-команда

д команда: удалить, удалить Подобно команде замены c выше

Удаление одной строки:

$ sed '2 d' 1.txt
This is first line.
This is third line.
This is four line.

Многострочная замена

$ sed '2,$ d' 1.txt
This is first line.

Или сопоставьте строки для замены:

$ sed '/This is/d' 1.txt
# 都木有了=-=

команда p

команда p: печать, команда печати, похожая на grep

# 匹配到third这一行,但是重复输出了
$ sed '/third/p' 1.txt
This is first line.
This is second line.
This is third line.
This is third line.
This is four line.
# 使用n参数进行过滤
$ sed -n '/third/p' 1.txt
This is third line.
# 多个模式匹配(两个模式中间的行次也会被匹配出来)
$ sed -n '/first/, /third/p' 1.txt
This is first line.
This is second line.
This is third line.
# 指定某一行到匹配行进行打印
$ sed -n '2,/four/p' 1.txt
This is second line.
This is third line.
This is four line.

Командная пакет

Несколько команд могут быть разделены точкой с запятой и заключены в фигурные скобки как вложенные команды:

# 从一二行中,匹配到This字符,然后整行进行删除
$ sed '1,2 {/This/d}' 1.txt
This is third line.
This is four line.
# 从一二行中,匹配到This字符,然后再匹配first字符,最后整行进行删除
$ sed '1,2 {/This/{/first/d}}' 1.txt
This is second line.
This is third line.
This is four line.
# 多命令用分号;分开
# 例如删掉包含first的行次,并且给每一行的开头加上#号
$ sed '1,$ {/first/d;s/^/#/g}' 1.txt
#This is second line.
#This is third line.
#This is four line.

Суммировать

Эти два инструмента документации так же просты в использовании, как grep, и я чувствую, что awk более мощный.Рекомендуется вам посетить классный блог дяди Мауса, который полон галантереи~


использованная литература

Сайт Крысиного Бога стоит посетить~

  1. Awk лаконичный учебник
  2. Краткое руководство по SED
  3. Веб-сайт инструментов регулярных выражений
  4. Документация по изучению регулярных выражений