У меня есть файл с 3 строками следующим образом. Используя linux, как я могу получить переменные разбиения строки и добавить ее к той же строке - PullRequest
0 голосов
/ 06 февраля 2020

Используя linux, как я могу получить желаемый выход ниже для данного входа. Входной файл:

Line1: StringA1, stringB1| stringC1, stringD1, stringE1
Line2: StringA2, stringB2| stringC2, stringD2
Line3: StringA3, stringB3| stringC3, stringD3, stringE3, stringF3

Мой вывод должен быть:

StringA1, stringB1| stringC1
StringA1, stringB1| stringD1
StringA1, stringB1| stringE1
StringA2, stringB2| stringC2
StringA2, stringB2| stringD2
StringA3, stringB3| stringC3
StringA3, stringB3| stringD3
StringA3, stringB3| stringE3
StringA3, stringB3| stringF3

Ответы [ 3 ]

2 голосов
/ 08 февраля 2020

Допущения:

  • все строки имеют как минимум 3 поля
  • строки не содержат строку Line#: (в противном случае нам просто нужно изменить предложенный скрипт)

Пример данных:

$ cat strings.dat
StringA1, stringB1| stringC1, stringD1, stringE1
StringA2, stringB2| stringC2, stringD2
StringA3, stringB3| stringC3, stringD3, stringE3, stringF3

Один awk раствор:

awk -F"[,|]" '
{ for ( i=3;i<=NF;i++ )
      { printf "%s,%s|%s\n", $1, $2, $i }
}' strings.dat

Где:

  • -F"[,|]" - использовать запятая и труба (,|) в качестве входных разделителей
  • for ( i=3;i<=NF;i++ ) - для полей от 3 до конца строки (NF == количество полей == последнее поле)
  • { printf ... } - выведите 1-е, 2-е и ith поля

Результаты выполнения вышеуказанного:

StringA1, stringB1| stringC1
StringA1, stringB1| stringD1
StringA1, stringB1| stringE1
StringA2, stringB2| stringC2
StringA2, stringB2| stringD2
StringA3, stringB3| stringC3
StringA3, stringB3| stringD3
StringA3, stringB3| stringE3
StringA3, stringB3| stringF3
1 голос
/ 07 февраля 2020

Когда вы принимаете решение в sed, его становится трудно читать и поддерживать:

sed -E 's/,/\v/; :a; s/(.*\|)(.*),(.*)$/\1\2\r\1\3/;ta; s/\v/,/g;s/\r/\n/g' inputfile

Объяснение:
s/,/\v/ Мост , должен быть заменен, но не тот, что в строке замены.
:a Повторите следующую команду (до ta), пока найдена замена.
(.*\|)(.*),(.*)$ Подберите 3 подстроки: стартер, середина part использует последнюю , и конечную часть.
\r Используйте windows CR в качестве маркера, где мы хотим, чтобы после завершения была новая строка.
\1 Замените на первую запомненную строку (в примере StringA1, stringB1).
/\1\2\r\1\3/ Заменить последний , маркером новой строки и стартером.
ta; Повторять до тех пор, пока не будут выполнены все замены.
s/\v/,/g; Восстановить символы , .
s/\r/\n/g' Замените маркер новой строки реальным символом новой строки.

Другие способы используют awk и while loop. Для большого файла я рекомендую awk, возможно, вы захотите попробовать это самостоятельно, прежде чем кто-то отправит ответ.

0 голосов
/ 08 февраля 2020

Чтобы получить желаемый результат, если вы разделяете на [,|], вы должны дополнительно удалить начало field1 перед выводом результатов. Есть два способа сделать это. Первый способ просто разбивает field1 на массив с fieldsep , равным ' ', второй - с комбинацией substr, match & length. Первый - это простой способ сделать это с помощью команды split(), например,

awk -F '[,|]' '{
    split ($1, arr, / /)
    for (i=3; i<=NF; i++) {
        printf "%s,%s|%s\n", arr[2], $2, $i
    }
}' file

Для второго вы можете удалить split() выше и заменить arr[2] на:

substr($1,match($1,/ /)+1,length($1)-match($1,/ /))

Если ваш файл данных не содержит "Line[0-9]: " в качестве префикса для каждой строки, вы можете включить следующее как printf для обработки любого случая:

printf "%s,%s|%s\n", arr[2]=="" ? arr[1] : arr[2], $2, $i

Результаты одинаковы либо путь, но рекомендуется использовать split().

Пример Использование / Вывод

Использование предложенного решения awk с вашим файлом данных (с именем * 1032) * отрегулируйте по мере необходимости), вы можете просто выбрать-скопировать / вставить среднюю мышь в xterm с помощью file в текущем каталоге, чтобы получить результаты, например,

$ awk -F '[,|]' '{
>     split ($1, arr, / /)
>     for (i=3; i<=NF; i++) {
>         printf "%s,%s|%s\n", arr[2], $2, $i
>     }
> }' file
StringA1, stringB1| stringC1
StringA1, stringB1| stringD1
StringA1, stringB1| stringE1
StringA2, stringB2| stringC2
StringA2, stringB2| stringD2
StringA3, stringB3| stringC3
StringA3, stringB3| stringD3
StringA3, stringB3| stringE3
StringA3, stringB3| stringF3

Просмотрите все и дайте Я знаю, если у вас есть дополнительные вопросы.

...