Почему разделитель полей awk не работает последовательно?

zshahora tiene un calificador global Ppara eso .

Para versiones anteriores, siempre puede usar:

f=(*.txt)
prog -f$^f

$^fhabilita la opciónrcexpandparampara la expansión de $f, donde las matrices se expanden en un estilo similar al del shell rc.

Enrc(ozsh -o rcexpandparam):

f=(*.txt)
prog -f$f

Se expande a prog -fa.txt -fb.txt, un poco como si hubiera escrito en csh (u otros shells que admitan la expansión de llaves):prog -f{a.txt,b.txt}.

(tenga en cuenta que es diferente de *.txt(P:-f:)en que el nombre del archivo está pegado a la opción -ffile.txten lugar de pasar dos argumentos-ffile.txt. Muchos comandos, incluidos todos aquellos que usan la API estándar getopt()para analizar opciones, admiten el paso de argumentos a opciones )en ambos sentidos.

fishtambién expande arreglos como ese:

set f *.txt
prog -f$f

En bash, puedes emularlo con:

f=(*.txt)
prog "${f[@]/#/-f}"

Conksh93:

f=(*.txt)
prog "${f[@]/*/-f\0}"

Para que -fy los file.txtcorrespondientes se pasen como argumentos separados, otra opción con zshusando su operador de compresión de matriz:

o=-f f=(*.txt); prog ${o:^^f}

Podría ampliar eso para su opción -g. Suponiendo que hay un número par de archivos txt:

o=(-g '') f=(*.txt); prog ${o:^^f}

Pasaría -gopciones con dos archivos a la vez. Similar a lo que obtendrías con:

printf -- '-g\0%s\0%s\0' *.txt | xargs -r0 prog

0
30.05.2019, 10:40
2 ответа

Как намекнул муру в комментарии , awk, вероятно, работает стабильно. Что может варьироваться, так это интервал в выводе ss.

Получается, чтоss -nt1 выводит семь столбцов, заголовки которых :State, Recv-Q, Send-Q, Local Address, Port, Peer Address, Port. Четвертый и пятый столбцы разделены двоеточием(:); то же самое для шестого и седьмого. Все остальные разделяются пробелом.
Все столбцы заполнены пробелами, где это необходимо для выравнивания. Четвертый и шестой дополняются слева, все остальные справа.

Может произойти дальнейшее заполнение:

  1. Если выход ss -ntнаправлен на клемму:

    1. если минимальная длина ее строк, вычисленная как сумма самого длинного содержимого для каждого поля плюс минимальное расстояние между (шестью символами ), меньше ширины терминала, каждая строка расширяется до ширину терминала, равномерно заполняя все столбцы пробелами;

    2. в противном случае строки разбиваются, а поля выравниваются по линиям (, заполненным, как указано выше, до ширины терминала ).

  2. Если выход ss -ntне направлен на клемму (, т.е. он перенаправляется или перенаправляется в обычный файл ), фактическая длина строк определяется как минимальное число, кратное 80, что превышает минимальную длину, определенную выше. Все столбцы равномерно заполняются пробелами для достижения общей длины строки, которая, следовательно, будет составлять 80, 160, 240,... символов 2 .

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

Тем не менее, вы можете обрабатывать вывод ss -tnдостаточно безопасным способом, учитывая, что заголовки столбцов известны и фиксированы и что, за исключением заголовков,ни один из его столбцов не должен содержать пробелов 3:

ss -nt | sed '
  1 s/[ ]Address:/_Address|/g           # Remove the known spaces from column
                                        # headers; also, change ":" into "|"
  s/:\([^:|]*[ ]\)/|\1/g                # Change the colons used as separators
                                        # into vertical bars "|", to avoid
  s/:\([^:|]*\)$/|\1/g                  # confusion with those in IPv6s
' | awk -v FS='\\||[ ]+' -v OFS=":" '   # Split on sequences of one or more
  { print $4,$5 }                       # spaces OR on any vertical bar
'

Это напечатает только четвертый и пятый столбцы (локальный адрес и порт ), разделенные двоеточием. Обратите внимание, что при использовании разделителя полей, который не является одиночным пробелом по умолчанию, awkбудет идентифицировать восемь столбцов вместо семи, и, если вы сделаете { $1=$1; print; }, он напечатает OFSв конце любой строки, для которой последний столбец справа -дополнен как минимум одним пробелом.


1Другие варианты (например. -i, -e,-m)резко меняют вывод ss. Для краткости и ясности мы сосредоточимся только на этой конкретной команде.
2Приблизительно и, возможно, неточно. Но это не имеет отношения к сути этого вопроса/ответа.
3По-видимому, это не гарантируется, мы намеренно не будем пытаться охватить все менее распространенные случаи.

3
28.01.2020, 02:15

Why isn't awk field separator working consistently?

Ненадежным является количество пробелов в выводе ss.

the fourth column, this is what I want.

Затем просто удалите заголовок(-H)и выберите четвертый столбец:

$ ss -taH | awk '{print $4}'
172.31.19.34:22
[::ffff:172.31.19.34]:80

Поскольку заголовок исправлен, просто добавьте его обратно (при необходимости):

$  echo "Local Address:Port"
Local Address:Port

Полная команда:

$ echo "Local Address:Port"; ss -tnH | awk '{print $4}'
Local Address:Port
172.31.19.34:22
[::ffff:172.31.19.34]:80

Да, ваш компьютер всегда имеет IPv6 (один или несколько )адресов. Если они вам не нужны, запрашивайте только адреса IPv4 :

.
$ ss -tnH4 | awk '{print $4}'
172.31.19.34:22
2
28.01.2020, 02:15

Теги

Похожие вопросы