Печать всех столбцов, кроме первых трех



слишком громоздким:



awk '{print " "" "" "" "" "" "" "" "" "" "}' things
581   17  
awk

17 ответов:

решение, которое не добавляет дополнительные ведущие или конечные пробел:

awk '{ for(i=4; i<NF; i++) printf "%s",$i OFS; if(NF) printf "%s",$NF; printf ORS}'

### Example ###
$ echo '1 2 3 4 5 6 7' |
  awk '{for(i=4;i<NF;i++)printf"%s",$i OFS;if(NF)printf"%s",$NF;printf ORS}' |
  tr ' ' '-'
4-5-6-7

Sudo_O предлагает элегантное улучшение с помощью тернарного оператора NF?ORS:OFS

$ echo '1 2 3 4 5 6 7' |
  awk '{ for(i=4; i<=NF; i++) printf "%s",$i (i==NF?ORS:OFS) }' |
  tr ' ' '-'
4-5-6-7

EdMorton дает решение, сохраняющее исходные пробелы между полями:

$ echo '1   2 3 4   5    6 7' |
  awk '{ sub(/([^ ]+ +){3}/,"") }1' |
  tr ' ' '-'
4---5----6-7

BinaryZebra также предоставляет два удивительных решения:
(эти решения даже сохранить конечные пробелы из исходной строки)

$ echo -e ' 1   2\t \t3     4   5   6 7 \t 8\t ' |
  awk -v n=3 '{ for ( i=1; i<=n; i++) { sub("^["FS"]*[^"FS"]+["FS"]+","",);} } 1 ' |
  sed 's/ /./g;s/\t/->/g;s/^/"/;s/$/"/'
"4...5...6.7.->.8->."

$ echo -e ' 1   2\t \t3     4   5   6 7 \t 8\t ' |
  awk -v n=3 '{ print gensub("["FS"]*([^"FS"]+["FS"]+){"n"}","",1); }' |
  sed 's/ /./g;s/\t/->/g;s/^/"/;s/$/"/'
"4...5...6.7.->.8->."

решение дано larsr в комментариях почти правильно:

$ echo '1 2 3 4 5 6 7' | 
  awk '{for (i=3;i<=NF;i++) $(i-2)=$i; NF=NF-2; print }' | tr  ' ' '-'
3-4-5-6-7

это фиксированная и параметризованная версия larsr устранение:

$ echo '1 2 3 4 5 6 7' | 
  awk '{for(i=n;i<=NF;i++)$(i-(n-1))=$i;NF=NF-(n-1);print }' n=4 | tr ' ' '-'
4-5-6-7

все остальные ответы до сентября-2013 хороши, но добавьте дополнительные пробелы:

awk '{for(i=1;i<4;i++) $i="";print}' file

использовать cut

$ cut -f4-13 file

или если вы настаиваете на awk и 13 $ - это последнее поле

$ awk '{==="";print}' file

другое

$ awk '{for(i=4;i<=13;i++)printf "%s ",$i;printf "\n"}' file

попробуйте это:

awk '{ =""; =""; =""; print  }'

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

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

$ echo '1   2 3 4   5    6' |
awk '{sub(/([^ ]+ +){3}/,"")}1'
4   5    6

если вы хотите разместить ведущие пробелы и непустые пробелы, но снова с FS по умолчанию, то это:

$ echo '  1   2 3 4   5    6' |
awk '{sub(/[[:space:]]*([^[:space:]]+[[:space:]]+){3}/,"")}1'
4   5    6

если у вас есть FS, который вы не можете отрицать в наборе символов, вы можете сначала преобразовать его в один символ (RS идеально подходит, если это один символ, так как RS не может появиться в поле, иначе рассмотрим SUBSEP), затем применить подстановку интервала RE, а затем преобразовать в OFS. например, если цепи "."с разделенными полями:

$ echo '1...2.3.4...5....6' |
awk -F'[.]+' '{gsub(FS,RS);sub("([^"RS"]+["RS"]+){3}","");gsub(RS,OFS)}1'
4 5 6

очевидно, что если OFS-это один символ, и он не может отображаться в полях ввода, вы можете уменьшить это к:

$ echo '1...2.3.4...5....6' |
awk -F'[.]+' '{gsub(FS,OFS); sub("([^"OFS"]+["OFS"]+){3}","")}1'
4 5 6

тогда у вас есть та же проблема, что и со всеми решениями на основе цикла, которые переназначают поля-FSs преобразуются в OFSs. Если это проблема, то вам нужно заглянуть в patsplit ГНУ соколы' (функция).

почти все ответы в настоящее время добавляют либо начальные пробелы, конечные пробелы или некоторые другие проблемы с разделителями. Чтобы выбрать из четвертого поля, где разделитель-пробел, а выходной разделитель-один пробел, используйте awk будет:

awk '{for(i=4;i<=NF;i++)printf "%s",$i (i==NF?ORS:OFS)}' file

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

awk '{for(i=n;i<=NF;i++)printf "%s",$i (i==NF?ORS:OFS)}' n=4 file

а также поле окончания:

awk '{for(i=n;i<=m=(m>NF?NF:m);i++)printf "%s",$i (i==m?ORS:OFS)}' n=4 m=10 file
awk '{==="";=;=}1'

вход

1 2 3 4 5 6 7

выход

4 5 6 7
echo 1 2 3 4 5| awk '{ for (i=3; i<=NF; i++) print $i }'

еще один способ избежать использования инструкции print:

 $ awk '{===""}sub("^"FS"*","")' file

в awk, когда условие истинно печать является действием по умолчанию.

Я не могу поверить, что никто не предложил простую оболочку:

while read -r a b c d; do echo "$d"; done < file

варианты от 1 до 3 имеют проблемы с несколькими пробелами (но просты). Это является причиной для разработки вариантов 4 и 5, которые обрабатывают несколько пробелов без проблем. Конечно, если варианты 4 или 5 используются с n=0 оба сохранят любые ведущие пробелы как n=0 значит нет разделения.

1

простое решение для вырезания (работает с одиночными разделителями):

$ echo '1 2 3 4 5 6 7 8' | cut -d' ' -f4-
4 5 6 7 8
2

форсирование awk re-calc иногда решите проблему (работает с некоторыми версиями awk) добавленных ведущих пространств:

$ echo '1 2 3 4 5 6 7 8' | awk '{ ==="";=;} NF=NF'
4 5 6 7 8
3

печать каждого поля, сформированного с помощью printf даст больше контроля:

$ echo '    1    2  3     4   5   6 7     8  ' |
  awk -v n=3 '{ for (i=n+1; i<=NF; i++){printf("%s%s",$i,i==NF?RS:OFS);} }'
4 5 6 7 8

однако все предыдущие ответы меняют все FS между полями на OFS. Давайте построим несколько решений для этого.

4

цикл с sub для удаления полей и разделителей является более портативным и не вызывает изменения FS на ОФС:

$ echo '    1    2  3     4   5   6 7     8  ' |
awk -v n=3 '{ for(i=1;i<=n;i++) { sub("^["FS"]*[^"FS"]+["FS"]+","",);} } 1 '
4   5   6 7     8

Примечание: "^["FS"]* " должен принимать входные данные с ведущими пробелами.

5

вполне возможно построить решение, которое не добавляет дополнительные начальные или конечные пробелы, а сохраняет существующие пробелы с помощью функции gensub от GNU awk, как это:

$ echo '    1    2  3     4   5   6 7     8  ' |
awk -v n=3 '{ print gensub("["FS"]*([^"FS"]+["FS"]+){"n"}","",1); }'
4   5   6 7     8 

он также может быть использован для замены списка полей с учетом количества n:

$ echo '    1    2  3     4   5   6 7     8  ' |
  awk -v n=3 '{ a=gensub("["FS"]*([^"FS"]+["FS"]+){"n"}","",1);
                b=gensub("^(.*)("a")","\1",1);
                print "|"a"|","!"b"!";
               }'
|4   5   6 7     8  | !    1    2  3     !

конечно, в таком случае OFS используется для разделения обеих частей строки, и конечное пустое пространство полей по-прежнему печатается.

Примечание 1:["FS"]* используется для разрешения лидирующих пробелов во входной строке.

Cut имеет флаг --complement, который позволяет легко (и быстро) удалять столбцы. Полученный синтаксис аналогичен тому, что вы хотите сделать-сделать решение проще для чтения/понимания. Дополнение также работает для случая, когда вы хотите удалить несмежные столбцы.

$ foo='1 2 3 %s 5 6 7'
$ echo "$foo" | cut --complement -d' ' -f1-3
%s 5 6 7
$

Perl решение, которое не добавляет ведущие или конечные пробелы:

perl -lane 'splice @F,0,3; print join " ",@F' file

perl @F autosplit массив начинается с индекса 0 в то время как awk поля начинаются с


Perl решение для данных, разделенных запятыми:

perl -F, -lane 'splice @F,0,3; print join ",",@F' file

Python решение:

python -c "import sys;[sys.stdout.write(' '.join(line.split()[3:]) + '\n') for line in sys.stdin]" < file

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

$ a='1   2\t \t3     4   5   6 7 \t 8\t '; 
$ echo -e "$a" | awk -v n=3 '{while (i<n) {i++; sub( FS"*", "")}; print }'

и если у вас есть больше строк для обработки, как например file фу.txt, не забудьте сбросить i до 0:

$ awk -v n=3 '{i=0; while (i<n) {i++; sub( FS"*", "")}; print }' foo.txt

благодаря вашему форуму.

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

у меня есть журнал, где после $5 с IP-адресом может быть больше текста или нет текста. Мне нужно все, от IP-адреса до конца строки, если там будет что-нибудь после $5. В моем случае это фактически с программой awk, не проявляющаяся заинтересовала, так что программисты должны решить проблему. Когда я пытаюсь удалить первые 4 поля, используя старый красивый и самый популярный, но совершенно неправильный ответ:

echo "  7 27.10.16. Thu 11:57:18 37.244.182.218 one two three" | awk '{====""; printf "[%s]\n", }'

он выплевывает неправильный и бесполезный ответ (я добавил [], чтобы продемонстрировать):

[    37.244.182.218 one two three]

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

echo "  7 27.10.16. Thu 11:57:18 37.244.182.218 one two three" | awk '{printf "[%s]\n", substr(,28)}'

который производит желаемый результат:

[37.244.182.218 one two three]

это не очень далеко от некоторых из предыдущих ответов, но не решить пару вопросов:

cols.sh:

#!/bin/bash
awk -v s= '{for(i=s; i<=NF;i++) printf "%-5s", $i; print "" }'

который теперь можно вызвать с аргументом, который будет стартовым столбцом:

$ echo "1 2 3 4 5 6 7 8 9 10 11 12 13 14" | ./cols.sh 3 
3    4    5    6    7    8    9    10   11   12   13   14

или:

$ echo "1 2 3 4 5 6 7 8 9 10 11 12 13 14" | ./cols.sh 7 
7    8    9    10   11   12   13   14

это 1-индексированный; если вы предпочитаете нулевой индексации, используйте .

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

#!/bin/bash
awk -v s= -v e= '{for(i=s; i<=e;i++) printf "%-5s", $i; print "" }'

например:

$ echo "1 2 3 4 5 6 7 8 9 10 11 12 13 14" | ./cols.sh 7 9 
7    8    9

The %-5s выравнивает результат в виде столбцов шириной 5 символов; если этого недостаточно, увеличьте число или используйте %s (с пробелом), а если вы не заботитесь о выравнивании.

решение на основе AWK printf, которое позволяет избежать проблемы % и уникально тем, что оно ничего не возвращает (без возвращаемого символа), если для печати требуется менее 4 столбцов:

awk 'NF > 3 { for(i=4; i<NF; i++) printf("%s ", $(i)); print $(i) }'

тестирование:

$ x='1 2 3 %s 4 5 6'
$ echo "$x" | awk 'NF > 3 { for(i=4; i<NF; i++) printf("%s ", $(i)); print $(i) }'
%s 4 5 6
$ x='1 2 3'
$ echo "$x" | awk 'NF > 3 { for(i=4; i<NF; i++) printf("%s ", $(i)); print $(i) }'
$ x='1 2 3 '
$ echo "$x" | awk 'NF > 3 { for(i=4; i<NF; i++) printf("%s ", $(i)); print $(i) }'
$

Comments

    Ничего не найдено.