Что следует использовать для извлечения полей и подстрок полей?

У меня есть файл с полями, разделенными вертикальной чертой. Я хочу напечатать подмножество поля 1 и все поле 2:

cat tmpfile.txt

# 10 chars.|variable length num|text
ABCDEFGHIJ|99|U|HOMEWORK
JIDVESDFXW|8|C|CHORES
DDFEXFEWEW|73|B|AFTER-HOURS

Я бы хотел, чтобы результат выглядел так:

# 6 chars.|variable length num
ABCDEF|99
JIDVES|8
DDFEXF|73

Я знаю, как получить поля 1 и 2:

cat tmpfile.txt | awk '{FS="|"} {print $1"|"$2}'

И знаете, как получить первые 6 символов поля 1:

cat tmpfile.txt | cut -c 1-6

Я знаю, что это довольно просто, но я не могу понять, как комбинировать команды awk и cut.

Любые предложения будут ценны.


person user3486154    schedule 01.04.2014    source источник


Ответы (4)


Вы можете использовать awk. Используйте функцию substr(), чтобы обрезать первое поле:

awk -F'|' '{print substr($1,1,6),$2}' OFS='|' inputfile

Для вашего ввода он выдаст:

ABCDEF|99
JIDVES|8
DDFEXF|73

Используя sed, вы могли бы сказать:

sed -r 's/^(.{6})[^|]*([|][^|]*).*/\1\2/' inputfile

для получения того же результата.

person devnull    schedule 01.04.2014
comment
+1; немного короче: awk -F'|' '{print substr($1,1,6) FS $2}' inputfile - person mklement0; 01.04.2014
comment
Если краткость важна: awk -F\| '{$0=substr($1,1,6)FS$2}1' - person Jotne; 01.04.2014
comment
Спасибо. Что означает 1 (а не 1 доллар) в данном контексте? - person user3486154; 01.04.2014
comment
@ user3486154 Вы можете считать это эквивалентом print. - person devnull; 01.04.2014
comment
@ user3486154 Это очень простая вещь в awk, то же самое, что и 1 {print $0}. Он просто печатает текущую строку. Или вы имеете в виду 1 в substr? Начните с позиции 1 строки. - person Jotne; 01.04.2014
comment
@Jotne Зачем вообще нужны фигурные скобки и 1. awk -F\| '$0=substr($1,1,6)FS$2' должно хватить. ;) - person jaypal singh; 01.04.2014
comment
@jaypal Умный :) Просто это всегда будет правдой, поэтому напечатано. - person Jotne; 01.04.2014
comment
Хороший! Иногда мне кажется более понятным использовать BEGIN{FS=OFS="|"}, когда оба FS / OFS одинаковы. - person fedorqui 'SO stop harming'; 02.04.2014
comment
@fedorqui Вы, наверное, правы в том смысле, что это более понятно. Мне кажется обременительным добавлять блок BEGIN и фигурные скобки, требующие нажатия клавиши Shift. Больно, ай! - person devnull; 02.04.2014

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

paste -d '|' <(cut -c 1-6 tmpfile.txt ) <(cut -d '|' -f2 tmpfile.txt )
person glenn jackman    schedule 01.04.2014

Просто для другого варианта: awk -F\| -vOFS=\| '{print $1,$2}' t.in | cut -c 1-6,11-

Кроме того, как отмечает Tripleee, это тоже можно сделать двумя разрезами: cut -c 1-6,11- t.in | cut -d\| -f 1,2

person Etan Reisner    schedule 01.04.2014
comment
Или, если вы можете угадать максимальную длину второго поля, используйте два разреза; cut -c1-6,11-16 t.in | cut -d'|' -f1-2 - person tripleee; 01.04.2014

Мне нравится комбинация cut и sed, но это всего лишь предпочтение:

cut -f1-2 -d"|" tmpfile.txt|sed 's/\([A-Z]\{6\}\)[A-Z]\{4\}/\1/g'

Результат:

# 10-digits|variable length num
ABCDEF|99
JIDVES|8
DDFEXF|73

Изменить: (Удалена бесполезная кошка) Спасибо!

person rpf    schedule 01.04.2014