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