*nix способ умножения строк после ','

У меня есть текстовый файл, который мне нужно настроить, чтобы я мог ввести его в базу данных.

Тем не менее, формат файла, хотя и согласован, не очень полезен, когда вы хотите поместить их в таблицы.

allow any 123.123.123.1,2,3 22,443

то, что мне нужно потом что-то вроде

allow any 123.123.123.1 22
allow any 123.123.123.1 443
allow any 123.123.123.2 22
allow any 123.123.123.2 443
allow any 123.123.123.3 22
allow any 123.123.123.3 443

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

Есть ли короткий способ сделать это с помощью инструментов обработки текста, таких как sed, tr и т. Д.?

3 ответа

Решение

Можно просто использовать расширение скобки

printf "%s\n" "allow any 123.123.123."{1,2,3}" "{22,443}


allow any 123.123.123.1 22
allow any 123.123.123.1 443
allow any 123.123.123.2 22
allow any 123.123.123.2 443
allow any 123.123.123.3 22
allow any 123.123.123.3 443

Может использовать Perl для генерации и запуска скобок

perl -ne 's/[^\.\s]+,[,\S]+/{$&}/g;s/[^{}\n]+(?![^{]*})/"$&"/g;print `printf "%s\n" $_`' f

Я придумал Awk Сценарий следующим образом, чтобы сделать работу за вас.

#!/usr/bin/awk

{
    n1=split($3,arr1,".")
    n2=split(arr1[n1],arr2,",")
    n3=split($4,arr3,",")

    k=arr1[1]"."arr1[2]"."arr1[3]

    for(i=1;i<=n2;i++) {
        for(j=1;j<=n3;j++) {
            print $1,$2,k"."arr2[i],arr3[j]
        }
    }
}

Поместите это в файл с именем script.awk и запустить его как

awk -f awkscript.awk file
allow any 123.123.123.1 22
allow any 123.123.123.1 443
allow any 123.123.123.2 22
allow any 123.123.123.2 443
allow any 123.123.123.3 22
allow any 123.123.123.3 443

Идея состоит в том, чтобы разделить содержимое $2 от . первым получить последнюю порцию в одиночку 1,2,3 к которому можно получить доступ как arr1[n], то есть последний элемент массива, который формируется после разбиения. Затем разделенный запятыми элемент теперь разделяется на , и хранится в массиве arr2 и так же для $4 запись. Переменная k создается только для хранения первых трех элементов в первом split()т.е. просто 123.123.123

Теперь выполняется цикл между элементами массива, сформированными для печати элементов по мере необходимости.

Просто для удовольствия sed (GNU sed версия 4.2.1):

sed -E -fallow.sed | sort

С помощью allow.sed:

s/^([^\n]+[^,[:digit:]])([[:digit:]]+(,[[:digit:]]+)*),([[:digit:]]+)([^\n]*)$/\1\2\5\n\1\4\5/;
:a;
s/^([^\n,]+[^,[:digit:]])([[:digit:]]+(,[[:digit:]]+)*),([[:digit:]]+)([^\n]*)\n(.*)$/\1\2\5\n\6\n\1\4\5/;
ta;
s/^([^,]+)\n(.*,.*)$/\2\n\1/;
ta;
  • Ищите разделенные запятыми группы чисел.
  • удвоить линию
    • удаление цифр перед последней запятой в одном экземпляре
    • удаление номера после последней запятой в другой копии
    • удаление последней запятой в обеих копиях
  • начать цикл здесь
  • сделать то же самое для того, что перед первым переводом строки
  • сохранить то, что после первой новой строки
  • цикл, если что-то было заменено
  • переместить запятую между символами новой строки (если есть) вперед
  • цикл, если был один

Выход:

allow any 123.123.123.1 22
allow any 123.123.123.1 443
allow any 123.123.123.2 22
allow any 123.123.123.2 443
allow any 123.123.123.3 22
allow any 123.123.123.3 443
Другие вопросы по тегам