Как этот awk выравнивает интервал?

Может кто-нибудь, пожалуйста, скажите мне, что это делает?

cat infile| awk ' { for(i=3;i<=NF;i++){ $2=$2" "$i } printf "%-4s %s\n", $1,$2 ; }' > outfile.txt 

infile содержит:

 1 John Smith 2 Bill Johnson ... 5000 George Heiz 

Я вижу, что результат состоит в том, что outfile.txt имеет все выровненные строки, но я не понимаю, как
В частности, что делает эта часть for(i=3;i<=NF;i++){ $2=$2" "$i } ?

С помощью этих awk скриптов я всегда считаю, что лучше всего их сломать, чтобы я мог видеть, что происходит.

Printf

Это легко. Это форматирует вывод исходных столбцов $1 и $2 так что столбец $1 заполняется так, что он занимает 4 пробела.

пример

 $ cat infile | awk ' { for(i=3;i<=NF;i++){ $2=$2" "$i } printf "%-4s DDD\n", $1 ; }' 1 DDD 2 DDD DDD 5000 DDD 

для цикла

Это немного сложнее обнаружить, но он принимает любые столбцы размером 3 или более и объединяет их в столбец $2 .

 $ cat infile | awk ' { for(i=3;i<=NF;i++){ $2=$2" "$i } printf "%s | %s\n", $2,$3 ; }' John Smith | Smith Bill Johnson | Johnson | George Heiz | Heiz 

Это немного облегчает, но, действительно, если мы добавим четвертый столбец в infile то это будет более очевидным:

 $ cat infile 1 John Smith 4thcol 2 Bill Johnson 4thcol 5000 George Heiz 4thcol 

пример

 $ cat infile | awk ' { for(i=3;i<=NF;i++){ $2=$2" "$i } printf "%s\t|\t%s\n", $2,$3 ; }' John Smith 4thcol | Smith Bill Johnson 4thcol | Johnson | George Heiz 4thcol | Heiz 

Если мы добавим 5thcol и т. Д., Они будут добавлены к $2 .

Этот awk-скрипт является запутанным и неэффективным способом делать то, что можно переписать таким образом:

 awk ' { f=$1 $1="" printf "%4d %s\n",f,$0 ; }' infile > outfile.txt 

Этот последний сценарий записывает в f-переменную первое поле, затем очищает его, затем печатает переменную f, выровненную по четырем символам, после чего оставшаяся исходная строка остается неизменной.

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

Редактировать:

Существует даже более простой способ, предложенный rici:

 awk '{$1 = sprintf("%4d", $1); print}' infile > outfile.txt 

Это просто заменяет первое поле его форматированным представлением и выводит строку.

У вас есть команды форматирования в printf как первая строка аргумента. %-4s указывает, что на выход будет выделено 4 символа и выровнено влево. Затем появляется пробел, за которым следует строка, обозначенная %s .