использование awk или sed для печати всех столбцов с n-го до последнего

Это НЕ дубликат другого вопроса. Все предыдущие вопросы / решения, опубликованные в stackoverflow, имеют ту же проблему: дополнительные пробелы заменяются одним пробелом.

Пример (1.txt)

filename Nospaces
filename One space
filename Two  spaces
filename Three   spaces

Результат:

awk '{$1="";$0=$0;$1=$1}1' 1.txt
One space
Two spaces
Three spaces

awk '{$1=""; print substr($0,2)}' 1.txt
One space
Two spaces
Three spaces

person meso_2600    schedule 30.03.2016    source источник
comment
@ hek2mgl Это НЕ дубликат другого вопроса. Все предыдущие вопросы / решения, опубликованные в stackoverflow, имеют ту же проблему: дополнительные пробелы заменяются одним пробелом.   -  person meso_2600    schedule 30.03.2016
comment
не у всех из них есть эта проблема. См., Например, ответы на stackoverflow.com/q/29514679/1745001.   -  person Ed Morton    schedule 30.03.2016
comment
Погодите - это был ВАШ вопрос! Вы приняли правильный ответ почти ровно год назад, а теперь снова задаете тот же вопрос. Что происходит?   -  person Ed Morton    schedule 30.03.2016


Ответы (5)


Чтобы сохранить пробелы в awk, вам придется использовать подстановки регулярных выражений или использовать подстроки. Как только вы начнете изменять отдельные поля, awk должен пересчитать $ 0, используя определенный (или неявный) OFS.

Ссылаясь на ответ Tom sed:

awk '{sub(/^([^[:blank:]]+[[:blank:]]+){1}/, "", $0); print}' 1.txt
person glenn jackman    schedule 30.03.2016
comment
этот код не работает - person meso_2600; 30.03.2016
comment
Это нормально с GNU awk. Какую awk вы используете? - person glenn jackman; 30.03.2016
comment
В этой старой версии используйте gawk --re-interval '...' - person glenn jackman; 30.03.2016
comment
ага, работает. но короче, никаких подписок уже отправлено в качестве ответа - person meso_2600; 30.03.2016
comment
одна проблема, если одна из этих строк содержит меньше столбцов, чем определенный n-й столбец, она печатается. fix: awk '{for (i = 0; i ‹[column_id]; i ++) sub (/ [^ [: space:]] + [[: space:]] * /,)} 1' Просто интересно, как это: пробел: отличается от: пусто: в этом случае - person meso_2600; 01.04.2016
comment
пробел включает вертикальные пробелы, например новую строку. - person glenn jackman; 01.04.2016

Укажите IFS с параметром -F, чтобы не пропускать несколько пробелов с помощью awk

awk -F "[ ]" '{$1="";$0=$0;$1=$1}1' 1.txt
awk -F "[ ]" '{$1=""; print substr($0,2)}' 1.txt
person jijinp    schedule 30.03.2016
comment
работает отлично. просто интересно, какие предостережения - person meso_2600; 30.03.2016
comment
Хм, теперь проблема в том, что я хочу начать со второго столбца, используя $ 1 = $ 2 = - person meso_2600; 30.03.2016
comment
Это работает даже для n-го столбца. - person jijinp; 30.03.2016
comment
нет, это не так, поскольку в последующих столбцах есть несколько пробелов - person meso_2600; 30.03.2016
comment
Отредактируйте свой вопрос, чтобы показать ожидаемый результат. - person jijinp; 30.03.2016

Если вы определяете поле как любое количество символов без пробела, за которым следует любое количество символов пробела, то вы можете удалить первый N следующим образом:

$ sed -E 's/([^[:space:]]+[[:space:]]*){1}//' file
Nospaces
One space
Two  spaces
Three   spaces

Измените {1} на {N}, где N - количество полей, которые нужно удалить. Если вы хотите удалить только 1 поле с самого начала, вы можете полностью удалить {1} (а также круглые скобки, которые используются для создания группы):

sed -E 's/[^[:space:]]+[[:space:]]*//' file

Некоторые версии sed (например, GNU sed) позволяют использовать сокращение:

sed -E 's/(\S+\s*){1}//' file

Если в начале строки может быть пробел, вы можете добавить \s* (или [[:space:]]*) в начало шаблона вне группы:

sed -E 's/\s*(\S+\s*){1}//' file

Проблема с использованием awk заключается в том, что всякий раз, когда вы касаетесь любого из полей данной записи, вся запись переформатируется, в результате чего каждое поле разделяется OFS (разделитель выходных полей), который по умолчанию является одним пробелом. Вы можете использовать awk с sub, если хотите, но поскольку это простая замена, sed - правильный инструмент для этой работы.

person Tom Fenech    schedule 30.03.2016
comment
это не работает для n-го столбца (2-го или 3-го) - person meso_2600; 30.03.2016
comment
не работает не очень четкое описание проблемы. Во всяком случае, я немного изменил его (используйте * вместо +). Я думаю, он должен сделать то, что вы ожидаете сейчас. - person Tom Fenech; 30.03.2016

Используйте 1_:

cut -d' ' -f2- a.txt

печатает все столбцы от второго до последнего и сохраняет пробелы.

person hek2mgl    schedule 30.03.2016
comment
пожалуйста, прочтите сначала вопрос - person meso_2600; 30.03.2016
comment
@ meso_2600 Эээ, извините, вы имеете в виду ссоры. Я бы использовал cut. Обновил ответ. - person hek2mgl; 30.03.2016
comment
и опять. пожалуйста, прочтите вопрос, это awk или sed;) - person meso_2600; 30.03.2016
comment
Я читаю это. Однако cut, очевидно, является правильным инструментом для работы. Обычно просьба сделать это с помощью инструмента A или B не одобряется, потому что вы уже предлагаете, вероятно, неправильное решение вопроса. Почему вы вынуждены использовать awk или sed? - person hek2mgl; 30.03.2016
comment
cat сталкивается с проблемами, когда IFS состоит из переменного количества пробелов, тогда как awk обрабатывает это правильно. Вот почему я упомянул n-ю колонку в вопросе. У cut возникают проблемы, как только я хочу напечатать 2- ›последнюю колонку - person meso_2600; 30.03.2016
comment
@ meso_2600 Я не могу воспроизвести это. В приведенном выше примере показано, как напечатать столбец со второго по последний. Если ваша настоящая проблема отличается от той, которая описана в вопросе, как мне тогда дать правильный ответ? - person hek2mgl; 30.03.2016

Рабочий код в awk, без ведущего пробела, поддержка нескольких пробелов в столбцах и печать из n-го столбца:

awk '{ print substr($0, index($0,$column_id)) }' 1.txt
person meso_2600    schedule 30.03.2016
comment
это просто детский правильный ответ :) - person meso_2600; 30.03.2016
comment
Хороший ответ. Возможный провал: одинаковый контент в двух разных столбцах. - person glenn jackman; 30.03.2016
comment
пожалуйста, поделитесь примером, так как я не могу воспроизвести такую ​​проблему - person meso_2600; 30.03.2016
comment
хорошо, я вижу проблему. благодаря. ваш ответ правильный - person meso_2600; 30.03.2016
comment
Для других: echo foo bar baz bar | awk -v column_id=4 '{print substr($0, index($0,$column_id))}' напечатает слишком много столбцов. - person glenn jackman; 30.03.2016
comment
Вы должны удалить его, прежде чем он наберет больше голосов против. - person Ed Morton; 30.03.2016
comment
Вот способ sed: FIELD=2 && sed "s/^\([^ ]*\([ ]*\)\)\{${FIELD}\}/\2/;s/ //" s.txt - person ; 30.03.2016