Подтвердить что ты не робот

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

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

awk '{print " "$4" "$5" "$6" "$7" "$8" "$9" "$10" "$11" "$12" "$13}' things
4b9b3361

Ответ 1

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

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"]+","",$0);} } 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 $0}' | 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 $0}' n=4 | tr ' ' '-'
4-5-6-7

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

Ответ 2

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

Ответ 3

использовать вырезать

$ cut -f4-13 file

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

$ awk '{$1=$2=$3="";print}' file

еще

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

Ответ 4

Попробуйте следующее:

awk '{ $1=""; $2=""; $3=""; print $0 }'

Ответ 5

Правильный способ сделать это - с интервалом 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, который RE не может отрицать в наборе символов, вы можете сначала преобразовать его в один char (RS идеален, если он один char, так как RS CAN NOT не отображается в пределах поле, в противном случае рассмотрите 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 является одиночным char И он не может появиться в полях ввода, вы можете уменьшить это:

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

Тогда у вас есть та же проблема, что и для всех решений на основе петли, которые переназначают поля - FS преобразуются в OFS. Если это проблема, вам нужно заглянуть в функцию patsplit() GNU awks.

Ответ 6

Практически все ответы в настоящее время добавляют либо ведущие пробелы, либо конечные пробелы, либо некоторые другие проблемы с разделителями. Чтобы выбрать из четвертого поля, где разделитель является пробелом, а разделитель вывода - одним пробелом, используя 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

Ответ 7

awk '{$1=$2=$3="";$0=$0;$1=$1}1'

Ввод

1 2 3 4 5 6 7

Выход

4 5 6 7

Ответ 8

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

Ответ 9

Другой способ избежать использования оператора печати:

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

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

Ответ 10

Не могу поверить, что никто не предлагал простой shell:

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

Ответ 11

Варианты с 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 иногда решает проблему (работает с некоторыми версиями awk) добавленных ведущих пробелов:

$ echo '1 2 3 4 5 6 7 8' | awk '{ $1=$2=$3="";$0=$0;} 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 в OFS:

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

Он также может использоваться для замены списка полей с учетом count 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"]* используется, чтобы позволить ведущие пробелы в строке ввода.

Ответ 12

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

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

Массив autosplit perl @F начинается с индекса 0, тогда как awk-поля начинаются с $1


Решение 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

Ответ 13

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

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

Ответ 14

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

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

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

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

Спасибо вашему форуму.

Ответ 15

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

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

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

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

[    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($0,28)}'

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

[37.244.182.218 one two three]

Ответ 16

Я нашел эту другую возможность, может быть, это может быть полезно также...

awk 'BEGIN {OFS=ORS="\t" }; {for(i=1; i<14; i++) print $i " "; print $NF "\n" }' your_file

Примечание: 1. Для табличных данных и от столбца $ 1 до $ 14

Ответ 17

Используйте вырезать:

cut -d <The character between characters> -f <number of first column>,<number of last column> <file name>

Например: если у вас есть file1 содержащий: car.is.nice.equal.bmw

Выполнить: cut -d. -f1,3 file1 cut -d. -f1,3 file1 напечатает car.is.nice

Ответ 18

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

cols.sh:

#!/bin/bash
awk -v s=$1 '{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-индекс; если вы предпочитаете нулевое индексирование, вместо этого используйте i=s + 1.

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

#!/bin/bash
awk -v s=$1 -v e=$2 '{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

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

Ответ 19

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) }'
$