*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