3

Я пытаюсь использовать sed для поиска определенного «первичного» шаблона, который может существовать в нескольких строках, с каждым первичным шаблоном, сопровождаемым --unknown-- количеством «вторичных» шаблонов.

Строки, содержащие шаблон, начинаются с: test(header_name) В этой же строке находится произвольное количество строк, следующих за ним. Я хочу переместить эти строки в их собственные строки, так что каждой из них предшествует собственный test(header_name) .

например Исходный файл (mytest.txt):

apples
test("Type1", "hat", "cat", "dog", "house");
bananas
oranges
test("Type2", "brown", "red", "green", "yellow", "purple", "orange");

Я хочу, чтобы это стало:

apples
test("Type1", "hat");
test("Type1", "cat");
test("Type1", "dog");
test("Type1", "house");
bananas
oranges
test("Type2", "brown");
test("Type2", "red");
test("Type2", "green");
test("Type2", "yellow");
test("Type2", "purple");
test("Type2", "orange");

Это было бы легко сделать, если бы мы знали количество строк в строке, но в этом случае оно не фиксировано.

Неуклюжий способ сделать это:

while ( a line exists that starts with 'test' and contains more than two args)
do

   Keep the first and second args
   Move the rest of that line to a new line and add 'test(header)' to the front

done

Но это отнимает много времени, особенно если есть сотни строк.

Есть идеи?

2 ответа2

1

Не красиво, но:

awk '
    /test\(/ {
        split($0, a)
        i=2
        while (a[i]) {
            sub(/(,|\);)$/, "", a[i])
            printf("%s %s);\n", a[1], a[i])
            i++
        }
        next
    }
    {print}
'
1

Хорошо, я нашел решение, используя цикл WHILE и SED. Да, это грязно, но это быстрее, чем алгоритм, который я опубликовал ранее!

# Look for first line that has more than two args
line_num=`sed -n -e '/test("[^"]*", "[^"]*",/{=;q}' myfile.txt`

while [ "$line_num" != "" ]
do

    # Get the first argument
    first_arg=`sed -ne ''$line_num' s/test("\([^"]*\)".*/\1/pg' myfile.txt`

    # All strings will be moved to their own line that includes 'test(first_arg)'
    sed -i -e ''$line_num' s/", "/\ntest("'"$first_arg"'", "/g' myfile.txt

    # No longer need first line after all targets moved to other lines     
    sed -i -e ''$line_num'd' myfile.txt


    # Check for remaining lines with more than two args
    line_num=`sed -n -e '/test("[^"]*", "[^"]*",/{=;q}' myfile.txt`

done


# Minor adjustments to the output (add close-quotation, close-bracket and semi-colon)
sed -i \
    -e 's/");//g' \
    -e 's/\(test("[^)]*\)/\1");/g' \
myfile.txt

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .