awk: Как выбрать несколько подстрок из файла фиксированной длины?

Я искал и искал, но на самом деле не нашел ответа на этот вопрос. Идея состоит в том, что у меня есть файл данных, из которого необходимы некоторые поля данных.

Примеры данных (test.dat)

50DI 20170510144200Mike Tester BL0004992000US 50ELI20170509145200Roy Developer BL0003400020MX 

Поэтому в случае, когда я хотел бы иметь второе поле данных, начиная с позиции 3 (DI или ELI) с длиной в три, я бы сделал следующее:

 awk '{print substr($0,3,3)}' test.dat 

Но я не могу понять, как получить несколько полей данных из исходного файла данных. Самое лучшее, что я придумал, это (отредактировано, когда я скопировал более старую версию).

 #!/bin/bash for i in {1..1}; do a=$(awk '{print substr($0,0,2)}' test.txt) b=$(awk '{print substr($0,20,7)}' test.txt) echo $a, $b done 

что

 50 50, Mike Roy 

вместо

 50, Mike 50, Roy 

Пример немного базовый, идея остается прежней: как мне получить несколько подстрок с awk? (Отказ от ответственности: я не женат на awk, я просто хочу поправиться с этим. Любые другие решения также высоко ценятся!)

  • Согласование и вставка в линию
  • Как извлечь строки между одинаковыми шаблонами из файла
  • Как я могу форматировать плоский файл с помощью awk?
  • Есть ли основной учебник для grep, awk и sed?
  • Как объединить все CSV S в один CSV в порядке
  • awk, вырезать символы из подстроки
  • введите число с нулями
  • Извлечение текстовых блоков на основе вывода grep
  • 3 Solutions collect form web for “awk: Как выбрать несколько подстрок из файла фиксированной длины?”

    С GNU awk , если вы действительно хотите фиксированную ширину:

     awk -v FIELDWIDTHS='2 17 7' -v OFS=', ' '{ print $1, $3 }' test.dat 

    С bash :

     while read -r line; do printf '%s, %s\n' "${line:0:2}" "${line:19:7}" done <test.dat 

    С несколько современными sed :

     sed 's/^\(..\).\{17\}\(.\{7\}\).*/\1, \2/' test.dat 

    С perl :

     perl -lpe '$_ = join ", ", unpack "A2x17A7"' test.dat 

    Выход для любого из вышеперечисленного:

     50, Mike 50, Roy 

    Как насчет cut ?

     cut -c1-2,20-26 --output-delimiter ', ' test.dat 50, Mike 50, Roy 

    Метод коротких седов :

     sed -En 's/^(.{2}).{17}(\S+).*/\1, \2/gp' test.dat 

    Выход:

     50, Mike 50, Roy 
    Linux и Unix - лучшая ОС в мире.