1

У меня есть файл, как показано ниже ..

"Field1"|"Field2"|"Field3"|"ufghjkrtyrtyfgh$"  
"Field1"|"Field2  
continue on line 2  
continue on line 3"|"Field3"|"ufghjkrtyrtyfgh$"  
"Field1"|"Field2"|"Field3"|"ufghjkrtyrtyfgh$"

Я ищу вывод, как показано ниже

"Field1"|"Field2"|"Field3"|"ufghjkrtyrtyfgh$"  
"Field1"|"Field2continue on line 2continue on line "|"Field3"|"ufghjkrtyrtyfgh$"  
"Field1"|"Field2"|"Field3"|"ufghjkrtyrtyfgh$"  
  1. Каждая запись заканчивается на $"
  2. Поле 2 может быть разбито на несколько строк
  3. Файл с разделителем трубы и двойная кавычка.

Не могли бы вы помочь мне решить эту проблему?

3 ответа3

3
$ awk '/[$]"[[:space:]]*$/{print;next} {printf "%s",$0}' file
"Field1"|"Field2"|"Field3"|"ufghjkrtyrtyfgh$"
"Field1"|"Field2continue on line 2continue on line 3"|"Field3"|"ufghjkrtyrtyfgh$"
"Field1"|"Field2"|"Field3"|"ufghjkrtyrtyfgh$"

Как это устроено

  • /[$]"[[:space:]]*$/{print;next}

    Для любой строки, которая заканчивается символом $ за которым следует " , за которым, возможно, следует пробел, this (1) печатает строку, а (2) пропускает оставшиеся команды и сообщает awk начать заново со next строки.

    В регулярных выражениях awk $ означает конец строки. Если мы хотим соответствовать действительному знаку доллара, мы должны как-то избежать его. Самый надежный способ избежать этого - заключить его в квадратные скобки: [$] . В приведенном выше регулярном выражении за [$] следует двойная кавычка " , за которой следует [[:space:]]* . Класс символов [[:space:]] соответствует любым символам пробела, а * означает, что мы должны соответствовать нулю или более из них. Далее следует неэкранированный $ который совпадает в конце строки.

  • printf "%s",$0

    Для любой другой строки это говорит awk печатать строку без символа новой строки.

1

Немного другое решение GNU awk :

awk -v RS='\\$" *' '{gsub(" *\n", ""); print $0 RT }' file

Это использует регулярное выражение в качестве разделителя записей.

1
echo '"Field1a"|"Field2a"|"Field3a"|"ufghjkrtyrtyfgh$"
"Field1b"|"Field2b
continue on line 2                              
continue on line 3"|"Field3b"|"ufghjkrtyrtyfgh$"
"Field1c"|"Field2c"|"Field3c"|"ufghjkrtyrtyfgh$"' | sed -nr '/^".*"$/{p;n};:a;/[^"]$|^[^"]/{N;s/(.)\n(.)/\1\2/;ta};p'
"Field1a"|"Field2a"|"Field3a"|"ufghjkrtyrtyfgh$"
"Field1b"|"Field2bcontinue on line 2continue on line 3"|"Field3b"|"ufghjkrtyrtyfgh$"
"Field1c"|"Field2c"|"Field3c"|"ufghjkrtyrtyfgh$"

Успешное решение. Будет напечатана каждая строка, начинающаяся и оканчивающаяся на «, затем команда« n »прочитает следующую строку и начнет новый цикл. Если строка не начинается и не заканчивается на «, она идет в цикл»:a .... ta ', затем команда «N» добавляет следующую строку, команда «s» заменяет «lastchar» «newline» «firstchar »(Часть« (.)\ N (.) »С« lastchar »« firstchar », затем команда« ta »переходит на метку«:a », только если команда« s »действительно заменяет что-то (это цикл) ). Если 's' ничего не заменяет, 'ta' не переходит к метке, а sed 'p' печатает результирующую строку и начинает новый цикл со следующей строки. Решение awk действительно кажется чище. Я думаю, что мое решение sed может быть улучшено.

Edit:-n опция подавляет автоматический вывод sed, поэтому мы печатаем только то, что нам нужно, с помощью p. Опция -r предназначена для расширенных регулярных выражений.

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