Изменить ширину первого столбца в файле с переменным количеством полей, используя awk

Рассчитайте сетевую маску или используйте подобный инструмент Онлайн-калькулятор IP CIDR , если у вас нет времени на расчеты,также вы не запомнили, что адреса 16384эквивалентны сети /18.

Введите в этот инструмент количество хостов(16384)и сетевой IP-адрес (46.43.64.0), и вы получите маску:255.255.192.0или 46.43.64.0/18в нотации сети CIDR.

Теперь измените правило iptables, чтобы отразить эту большую сеть :

.

iptables -A INPUT -s 46.43.64.0/18 -j ACCEPT

Используя эту нотацию CIDR в своих правилах, вы можете разрешать более широкие сети по своему усмотрению, вместо того, чтобы перечислять все /24сети, которые интегрируют эту более широкую маску.

Другой способ сделать это — создать правило, основанное на src-range.

iptables -A INPUT -m iprange --src-range 46.43.64.0-46.43.127.255 -j ACCEPT

Я не знаю, как этот подход повлияет на производительность фильтрации, поэтому я бы выбрал первый вариант

10
15.09.2019, 15:07
4 ответа

Вы можете использовать sprintfтолько для повторного -формата $1.

Пр.

$ awk 'BEGIN{OFS=FS="|"} {$1 = sprintf("%-3s",$1)} 1' file
c1 |c2|c3|c4|c5
c6 |c7|c8|c9|c10
c11|c12|c13|c14|c15
14
27.01.2020, 20:00

Разумный способ — это то, что предложил стилдрайвер . Бесполезно запутанный способ — перебирать каждое поле :

.
$ awk -F'|' '{printf "%-3s|",$1; for(i=2;i<NF;i++){printf "%s|",$i} printf "%s\n", $i}' file
c1 |c2|c3|c4|c5
c6 |c7|c8|c9|c10
c11|c12|c13|c14|c15

Но простоsprintf$1и покончим с этим.

1
27.01.2020, 20:00

Чтобы вычислить наибольшую/наибольшую длину первого поля, а затем переформатировать значения в поле в соответствии с этой длиной, вам придется выполнить два отдельных прохода по файлу.

awk 'BEGIN     { OFS = FS = "|" }
     FNR == NR { if (m < (n=length($1))) m = n; next }
               { $1 = sprintf("%-*s", m, $1); print }' file file

(обратите внимание, что входной файл указывается дважды в командной строке)

Для данных, которые вы представляете, это даст

c1 |c2|c3|c4|c5
c6 |c7|c8|c9|c10
c11|c12|c13|c14|c15

Первый проход обрабатывается блоком FNR == NR, который просто отслеживает самое длинное поле, видимое до сих пор, (m, содержит максимальную видимую длину ), и переходит к следующей строке.

Второй проход обрабатывается последним блоком, который переформатирует первое поле, используя sprintf(). Строка формата %-*sозначает «выровненную по левому краю -строку, ширина которой задается целочисленным аргументом перед аргументом, содержащим фактическую строку».

Это, очевидно, можно было бы расширить, чтобы сделать все столбцы, превратив скаляр mв массив, который содержит максимальную ширину каждого столбца:

$ awk 'BEGIN     { OFS = FS = "|" }
       FNR == NR { for (i=1; i<=NF; ++i) if (m[i] < (n=length($i))) m[i] = n; next }
                 { for (i=1; i<=NF; ++i) $i = sprintf("%-*s", m[i], $i); print }' file file
c1 |c2 |c3 |c4 |c5
c6 |c7 |c8 |c9 |c10
c11|c12|c13|c14|c15
6
27.01.2020, 20:00

В Awk вы можете использовать " *" для создания динамической строки формата printf.

Если вы уже знаете длину, вы можете передать длину поля для первого столбца с помощью -v.

awk -vcol1=3 'BEGIN{FS="|"}{for(i=1;i<=NF;i++){if(i==1)printf "%*-s%s",col1,$i,FS;else if(i!=NF)printf "%s%s",$i,FS;else printf "%s\n",$i;};}' test.txt

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

1
27.01.2020, 20:00

Теги

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