Команда awk для разделения второго столбца

Правду сказать, мне просто лень сходить с 17.3 - у меня работает. При этом мне все еще нужен был более новый gcc. Чтобы повторно скомпилировать его для разных целей, у меня есть скрипт bash (см. ниже), который я модифицирую и запускаю (я пишу свою собственную игрушечную ОС, поэтому мне приходится использовать специально сгенерированный gcc).

Измените каталоги в приведенном ниже скрипте, чтобы они соответствовали имеющимся у вас каталогам. Я храню скомпилированную версию в своем собственном каталоге, чтобы легко переключаться между моей скомпилированной версией и версией системы. Я предлагаю вам сделать то же самое. Вам необходимо скачать binutils-2.23.2, а также интересующую вас версию gcc (ниже я использую 7.1.0).Поместите их в каталог ~/contrib вместе со скриптом ниже.

Вы также можете изменить строку "--enabled-languages=c" на "--enabled-languages=c,c++,objc" - моему проекту нужен только C. Другим изменением будет значение PLATFORM. Я использую "i686-elf", но это не сработает для вас (ниже я изменил его на что-то, что будет работать на 32-битной платформе). Вы можете попробовать "x86_64-linux-gnu" для 64-битной платформы.

Для любопытных: причина, по которой я собираю его таким образом, заключается в том, что в процессе сборки gcc раньше была ошибка, препятствовавшая перестроению в исходном каталоге. Я не знаю, существует ли эта ошибка до сих пор (последний раз я столкнулся с ней в 4.8.0), но единственным обходным путем была явная сборка в отдельном каталоге, если вы когда-нибудь захотите пересобрать.

[EDIT: Выполните установку зависимостей, предложенных выше GAD3R]

#!/bin/bash

function die() {
   echo $1
   exit 127
}


export PREFIX=/home/lelanthran/opt/cross
export TARGET=i686-linux-gnu
export PATH="$PREFIX/bin:$PATH"

pushd $PWD &> /dev/null
mkdir -p build-binutils
cd build-binutils
../binutils-2.23.2/configure \
   --target=$TARGET \
   --prefix="$PREFIX" \
   --with-sysroot \
   --disable-nls \
   --disable-werror || die "binutils/config error"
make           || die "binutils/make error"
make install   || die "binutils/make install error"

popd &> /dev/null

pushd $PWD &> /dev/null
mkdir -p build-gcc-7.1.0
cd build-gcc-7.1.0
../gcc-7.1.0/configure \
   --target=$TARGET \
   --prefix="$PREFIX" \
   --disable-nls \
   --enable-languages=c \
   --without-headers || die "gcc/config error"
make all-gcc                  || die "gcc/make all-gcc error"
make all-target-libgcc        || die "gcc/make all-target-libgcc error"
make install-gcc              || die "gcc/make install-gcc error"
make install-target-libgcc    || die "gcc/make install-target-libgcc error"
0
20.06.2017, 18:28
3 ответа

awkрешение:

awk -F'|' 'NF>1 && $2~/[^,]+,[^,]*/{ 
           len=split($2,a,","); 
           for(i=1;i<=len;i++) { 
               if(a[i]!="") print $1,a[i] 
           } 
           next }1' OFS='|' file

Выход:

Item1|keys
Item1|books
Item1|helmet
Item1|handle
Item2|Bike
Item3
Item4|Tyre
Item4|brakes
Item4|headlight
Item4|clamps
Item4|rollergrip
Item5|Nails
Item5|hammers

Детали:

  • -F'|'-разделитель полей

  • NF>1 && $2~/[^,]+,[^,]*/-учитывает как минимум 2 поля со значениями, разделенными запятыми -во втором поле

  • len=split($2,a,",")-разделить второе поле на массив aс помощью разделителя ,. Переменной lenприсваивается размер массива (количество чанков)

  • for(i=1;i<=len;i++)перебор " фрагментов "

  • if(a[i]!="") print $1,a[i]-распечатать все связанные последовательности, кроме пустых значений

1
28.01.2020, 02:25
sed -e 's/,$//' -e '/^[^|]*$/s/$/|/' file.in |
awk -F'[|,]' -vOFS='|' '{ for (i = 2; i <= NF; ++i) { print $1, $i } }'

sedвыполняет предварительную обработку входных данных. Он удаляет конечные запятые в конце каждой строки (-e 's/,$//'), а если строка не содержит символ вертикальной черты, добавляет ее в конец(-e '/^[^|]*$/s/$/|/').

Данные примера преобразуются в следующие с помощью фильтра sed:

Item1|keys,books,helmet,handle
Item2|Bike
Item3|
Item4|Tyre,brakes,headlight,clamps,rollergrip
Item5|Nails,hammers

Сценарий awkберет это и интерпретирует каждую строку как набор полей, разделенных вертикальной чертой или запятой(-F'[|,]'). Затем для каждой входной строки он будет повторно соединять первое поле с каждым из других полей и выводить их. Каждая пара полей в выходных данных разделена вертикальной чертой (-vOFS='|').

Результат

Item1|keys
Item1|books
Item1|helmet
Item1|handle
Item2|Bike
Item3|
Item4|Tyre
Item4|brakes
Item4|headlight
Item4|clamps
Item4|rollergrip
Item5|Nails
Item5|hammers
1
28.01.2020, 02:25

Другая awkверсия

  • установить разделитель полей на |или,
  • если в записи менее 2 полей, выведите ее как -равно
  • else перебирает все поля от 2 до NF-1печатает $1и$i(это пропускает пустое поле $NF, вызванное завершающей запятой

т.е.

$ awk 'NF<2 ; {for (i=2;i<NF;i++) print $1,$i}' FS='[|,]' OFS='|' file
Item1|keys
Item1|books
Item1|helmet
Item1|handle
Item2|Bike
Item3
Item4|Tyre
Item4|brakes
Item4|headlight
Item4|clamps
Item4|rollergrip
Item5|Nails
Item5|hammers
1
28.01.2020, 02:25

Теги

Похожие вопросы