Как обрезать второй столбец до заданной длины

9

Учитывая ввод формы

XY981743    foobarlkasdf saflkas asfZR!sgfad asdSAD asdsadf SAdfasdf46lk lksad bar foolkasjfdrte

как я могу обрезать только второй столбец? Разделителем является TAB, а длина второго столбца должна быть не более 75 символов.

LoukiosValentine79
источник
Немного более обобщенно:awk 'BEGIN{OFS=FS="\t"} {$2=substr($2,1,75)}1' file
fedorqui
Хотите обрезать (удалить символы после 75-го) или сложить (напечатать их на другой строке)? Кроме того, следует ли считать пробелы в 75 символов или нет?
Тердон

Ответы:

7

Если вы хотите напечатать только первые 75 символов второго столбца (включая пробелы и предполагая, что в файле только два столбца), вы можете сделать:

$ perl -pe 's/(\t.{75}).*/$1/' file
XY981743    foobarlkasdf saflkas asfZR!sgfad asdSAD asdsadf SAdfasdf46lk lksad bar fool

Или с GNU sed:

$ sed 's/\(.*\t.\{75\}\).*/\1/' file
XY981743    foobarlkasdf saflkas asfZR!sgfad asdSAD asdsadf SAdfasdf46lk lksad bar fool

Или:

$ sed -r 's/(.*\t.{75}).*/\1/' file
XY981743    foobarlkasdf saflkas asfZR!sgfad asdSAD asdsadf SAdfasdf46lk lksad bar fool

В качестве альтернативы вы можете использовать foldуказание обрезать первые 91 символ (это 8 для идентификатора и еще 8 для вкладки) и вывести только первую строку:

$ fold -w 91 file | head -n1
XY981743    foobarlkasdf saflkas asfZR!sgfad asdSAD asdsadf SAdfasdf46lk lksad bar fool

Если ваш файл может иметь более 2 столбцов и вы хотите только усечь второй, вы можете это сделать (что, как я только что заметил, является лишь перепиской ответа Стивена ):

$ awk -F"\t" -vOFS="\t" '{$2=substr($2,1,75)}1;' file
XY981743    foobarlkasdf saflkas asfZR!sgfad asdSAD asdsadf SAdfasdf46lk lksad bar fool

Или (обратите внимание, что это сломается, если первые 75 символов 2-го столбца можно будет интерпретировать как регулярное выражение):

$ perl -F"\t" -pale 's/$F[1]/substr($F[1],0,75)/e' file
XY981743    foobarlkasdf saflkas asfZR!sgfad asdSAD asdsadf SAdfasdf46lk lksad bar fool
Тердон
источник
Они могут обрезать столбцы, отличные от второго. Ваша первая sedкоманда также использует GNUism ( \t).
Стефан Шазелас
@ StéphaneChazelas что ? \tтакое GNUism? Шутки в сторону? Каков переносимый способ описания вкладки тогда?
Тердон
1
Вставьте это дословно или посмотрите мой ответ. Единственная escape-последовательность, распознаваемая переносимо на LHS, \n(и опять же не [...]во многих реализациях), ни одна на RHS.
Стефан Шазелас
@ StéphaneChazelas, черт побери, спасибо. Я также добавил решение, которое может обрабатывать несколько столбцов.
Тердон
Ваш последний perlимеет мало смысла. Подумайте, например, о входе, какaba\t.*
Стефан Chazelas
10

Используя awk, разделите файл с помощью вкладок и выведите первое поле полностью и первые 75 символов (самое большее) второго:

awk -F "\t" 'BEGIN { OFS=FS }; { print $1, substr($2, 1, 75); }'

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

awk -F "\t" 'BEGIN { OFS=FS }; { $2=substr($2, 1, 75); print }'

Вы можете применить substrк нескольким полям, зацикливая их при необходимости.

Стивен Китт
источник
@ Стефан, в каких случаях нужно дополнительное ;?
Стивен Китт
Они требуются POSIX. Сейчас я не знаю ни одной реализации, где они требуются, но когда я попросил, чтобы требование POSIX было смягчено, оно было отклонено сопровождающим gawk (где все примеры в документе имеют символ;).
Стефан Шазелас
Ах, приятно знать, спасибо! Таким образом, спецификация и документация более строгие, чем все реализации ...
Стивен Китт
все реализации, которые я знаю по крайней мере (не так много). Дело в том, что пропустить разделитель для нестандартного синтаксиса. Таким образом, текущие и будущие реализации могут и имеют право задушить его или ввести расширения, которые его используют (например, для обработки исключений /pattern/ {action} {exception-handling}). Теперь это было бы крайне маловероятно, если учесть, что пропуск этих правил ;довольно распространен.
Стефан Шазелас
4

Портативно / POSIXly с sed:

tab=$(printf '\t')
sed "s/\($tab[^$tab]\{0,75\}\)[^$tab]*/\1/"

Или обрезать каждый столбец:

sed "s/\([^$tab]\{75\}\)[^$tab]*/\1/g"
Стефан Шазелас
источник
2

Если есть только 2 столбца:

sed -r 's/^([^\t]*\t)(.{0,75}).*/\1\2/'

{0,75}означает выбрать от 0 до 75 символов.
.* это удаленный раздел за 75 символов


Если есть 2 или более столбцов:

sed -r 's/^([^\t]*\t)([^\t]{0,75})[^\t]*(.*)/\1\2\3/' file

[^\t]* это удаленный раздел за 75 символов

Peter.O
источник
Обратите внимание, что это предполагает GNU, sedа это POSIXLY_CORRECTне в окружающей среде ..
Стефан Шазелас