2013-08-27 2 views
14

Предположим, у нас есть этот файл данных.печатать остальную часть полей в awk

john 32 maketing executive 
jack 41 chief technical officer 
jim 27 developer 
dela 33 assistant risk management officer 

Я хочу напечатать с помощью awk

john maketing executive 
jack chief technical officer 
jim developer 
dela assistant risk management officer 

Я знаю, что это может быть сделано с помощью for.

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

Проблема в ее долгой и выглядит сложной.

Есть ли другой короткий путь для печати Остальные поля.

+0

Простой взлом - установить $ 2 на "", а затем напечатать $ 0 (все поля), хотя это даст вам дополнительный разделитель для пустого поля. – mkfs

+0

Через 3 года ты помог мне. Но вы должны изменить « Koreth

ответ

28

В поле (ы) вы хотите, чтобы перейти к пустым:

awk '{$2 = ""; print $0;}' < file_name 

Источник: Using awk to print all columns from the nth to the last

+2

Не очищает лишнее пространство и использует ненужный 'print $ 0', который может быть заменен простым' 1' – Jotne

+0

@Jotne Когда я использую '1' на месте' print $ 0', я не получаю никакого вывода из awk. Вы уверены, что они эквивалентны? – Alex

+0

не работал для пропусков первого пустого – malhal

3

Вы можете использовать простой AWK как это:

awk '{$2=""}1' file 

Однако это будет иметь дополнительные OFS на вашем выходе, которые можно избежать этим awk

awk '{sub($2 OFS, "")}1' file 

или же с помощью этого тр и вырезать комбо:

В Linux:

tr -s ' ' < file | cut -d ' ' -f1,f3- 

На OSX:

tr -s ' ' < file | cut -d ' ' -f1 -f3- 
+0

Это должно быть 'cut -d '' -f1,3-'. –

+0

@ AdrianFrühwirth: Спасибо, но 'cut -f1,3-' не переносится и не поддерживается на моем OSX. – anubhava

+0

Затем вырезается OSX 'cut'. [POSIX] (http://pubs.opengroup.org/onlinepubs/007904975/utilities/cut.html) говорит, что * Приложение должно гарантировать, что список опционных аргументов (см. Параметры -b, -c и -f ниже) представляет собой список, разделенный запятыми [...] *, и '-f -f' перерывает мой Linux с помощью' coreutils-8.16' с сообщением об ошибке * cut: может быть указан только один тип списка *. –

4

Это удаляет поданную # 2 и очищает дополнительное пространство.

awk '{$2="";sub(" "," ")}1' file 
+0

Что это делает '1' здесь? –

+2

@ shiplu.mokadd.im «1» оценивает значение true, которое ударяет по блоку по умолчанию ('{print $ 0}'). –

+0

Не чистит ничего, но вместо этого, как и все перезаписи существующих полей, он заменяет 'IFS' (одну или несколько строк) на единую' OFS'. Например. это один из способов реализовать фильтр «normalize spaces»: 'awk '{$ 1 = $ 1} 1'' –

2

Другим способом является просто использовать СЭД, чтобы заменить первые цифры и пространство матча:

sed 's|[0-9]\+\s\+||' file

8

Достоверно с GNU AWK для gensub() при использовании FS по умолчанию:

$ gawk -v delNr=2 '{$0=gensub("^([[:space:]]*([^[:space:]]+[[:space:]]+){"delNr-1"})[^[:space:]]+[[:space:]]*","\\1","")}1' file 
john maketing executive 
jack chief technical officer 
jim developer 
dela assistant risk management officer 

С другими awks вам нужно использовать match() и substr() вместо gensub(). Обратите внимание, что переменная delNr выше говорит AWK, какое поле вы хотите удалить:

$ gawk -v delNr=3 '{$0=gensub("^([[:space:]]*([^[:space:]]+[[:space:]]+){"delNr-1"})[^[:space:]]+[[:space:]]*","\\1","")}1' file 
john 32 executive 
jack 41 technical officer 
jim 27 
dela 33 risk management officer 

Не делай этого:

awk '{sub($2 OFS, "")}1' 

как тот же текст, который в $ 2 может быть в конце $ 1, и/или $ 2 могут содержать метасимволы RE, поэтому есть очень хороший шанс, что вы удалите неправильную строку таким образом.

Не делайте этого:

awk '{$2=""}1' file 

как это добавляет FS и будет сжимать все другое смежное белое пространство между полями в один пустой полукокс каждого.

Не делайте этого:

awk '{$2="";sub(" "," ")}1' file 

как это hasthe вопрос пространственно-сжатия, упомянутых выше, и опирается на жестко прописанных ФС одной пустой (по умолчанию, хотя, так что, возможно, не так уж плохо), но что более важно, если бы существовали пробелы до 1 доллара, он удалял один из них вместо пространства, добавляемого между $ 1 и $ 2.

Следует упомянуть, что в последних версиях gawk есть новая функция patsplit(), которая работает как split(), но в дополнение к созданию массива полей, она также создает массив пространств между полями. Это означает, что вы можете манипулировать полями и промежутками между ними в массивах, поэтому вам не нужно беспокоиться о том, что awk перекомпилирует запись, используя OFS, если вы манипулируете полем. Затем вам просто нужно напечатать нужные поля из массивов. См. Patsplit() в http://www.gnu.org/software/gawk/manual/gawk.html#String-Functions для получения дополнительной информации.

+1

Этот ответ не такой быстрый и грязный, но человек может научиться этому. +1 для информации. – Kent

+0

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

+0

Зависит от вашего ввода. Если у вас есть один символ между полями, тогда 'cut' лучше. Если у вас есть что-то еще, то gawk + gensub() или sed (очень похожие синтаксически) могут быть лучшими опциями. Обе из них могут столкнуться с проблемами при попытке описать отрицание многозначных RE, поэтому вам нужно взглянуть на gawk + patsplit() или gawk + FPAT. К сожалению, нет серебряной пули. –

Смежные вопросы