WedX - журнал о программировании и компьютерных науках

Удалите \n в нескольких строках с помощью sed

Я пытаюсь использовать sed для удаления всех символов новой строки между двумя шаблонами поиска.

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

sed -e '/begin/,/end/{s/begin/replacement/p;d}'

Затем я нашел этот пост, чтобы удалить все новые строки в файле.

sed ':a;N;$!ba;s/\n/ /g'

Я попытался объединить два ответа и придумал:

sed -e '/begin/,/end/{:a;N;$!ba;s/\n/ /p;d}'

Однако это не совсем работает. Он заменяет новые строки, начиная с правильной строки, но продолжается до конца файла. Пример приведен ниже:

Сэд Команда:

sed -e '/Seven/,/Fifteen/{:a;N;$!ba;s/\n/ /g}' input.txt

ввод.txt:

One Two Three
Four Five Six
Seven Eight Nine
Ten Eleven Twelve
Thirteen Fourteen Fifteen
Sixteen Seventeen Eighteen
Nineteen Twenty Twenty-One

Выход:

One Two Three
Four Five Six
Seven Eight Nine Ten Eleven Twelve Thirteen Fourteen Fifteen Sixteen Seventeen Eighteen Nineteen Twenty Twenty-One

Чего я действительно хочу:

One Two Three
Four Five Six
Seven Eight Nine Ten Eleven Twelve Thirteen Fourteen Fifteen
Sixteen Seventeen Eighteen
Nineteen Twenty Twenty-One

Спасибо за любую помощь!

23.08.2014

Ответы:


1

Вам нужно изменить $ на /Fifteen/:

sed -e '/Seven/,/Fifteen/{:a;N;/Fifteen/!ba;s/\n/ /g}' input.txt

  • $!ba => перейти к a, если не последняя строка
  • /Fifteen/!ba => перейти к a, если не соответствует /Fifteen/

Вы можете сделать команду короче:

sed '/Seven/{:a;N;/Fifteen/!ba;s/\n/ /g}' input.txt
23.08.2014
  • Поскольку вы управляете циклом в блоке кода, вам не нужно ,/Fifteen/ в начальном адресе. 23.08.2014
  • Остерегайтесь, что /Seven/... будет дважды совпадать в приведенных примерах данных, первое, как и ожидалось, но также и с Seventeen. Это никогда не совпадает с последующим Fifteen, поэтому заканчивается концом файла и командой N. Поскольку это может привести к неожиданным результатам, если вышеуказанная команда будет улучшена, возможно, /\<Seven\>/ может быть безопаснее. 23.08.2014

  • 2

    Вот awk версия:

    awk '/Seven/ && !g {f=1;g=1} /Fifteen/ {f=0} {printf "%s%s",$0,(f?FS:RS)}' file
    One Two Three
    Four Five Six
    Seven Eight Nine Ten Eleven Twelve Thirteen Fourteen Fifteen
    Sixteen Seventeen Eighteen
    Nineteen Twenty Twenty-One
    

    Вот версия gnu awk (границы слов):

    awk '/\<Seven\>/ {f=1} /\<Fifteen\>/ {f=0} {printf "%s%s",$0,(f?FS:RS)}' file
    One Two Three
    Four Five Six
    Seven Eight Nine Ten Eleven Twelve Thirteen Fourteen Fifteen
    Sixteen Seventeen Eighteen
    Nineteen Twenty Twenty-One
    

    Другая awk версия:

    awk '/Seven/ && !/Seven[[:alnum:]]/ && !/[[:alnum:]]Seven/ {f=1} /Fifteen/ {f=0} {printf "%s%s",$0,(f?FS:RS)}' file
    One Two Three
    Four Five Six
    Seven Eight Nine Ten Eleven Twelve Thirteen Fourteen Fifteen
    Sixteen Seventeen Eighteen
    Nineteen Twenty Twenty-One
    
    23.08.2014
  • +1 относительно printf "%s"(f?FS:RS),$0, хотя в этом случае он будет вести себя так, как ожидалось, просто имейте в виду, что он потерпит неудачу, если FS или RS когда-либо будут содержать символ %. Это безопаснее и ИМХО намного понятнее, поскольку он перемещает разделитель после $0, где он печатается, чтобы написать printf "%s%s",$0,(f?FS:RS). К вашему сведению, в не-глауках вы можете использовать /(^|[^[:alnum:]_])Seven([^[:alnum:]_]|$)/ вместо /\<Seven\>/, поэтому вам не нужно писать /Seven/ && !/Seven[[:alnum:]]/ && !/[[:alnum:]]Seven/ 23.08.2014
  • Бенджамин - основное различие между приведенным выше и опубликованным мной решением заключается в том, как они будут себя вести, если во входном файле присутствует Seven, а Fifteen нет. Мой не внесет никаких изменений, в то время как Jotne заменит все новые строки пробелами после Seven до конца файла. Очевидно, что это желаемое поведение, поскольку вы не указали. 23.08.2014
  • @EdMorton Я согласен, что лучше использовать "%s%s",$0,(f?FS:RS), но чтобы FS или RS содержали %, вам нужно установить его. 23.08.2014
  • Верный. Хотя не совсем уверен, что понимаю вашу мысль. Я просто говорю, что использование этого синтаксиса не удастся, если вам нужно настроить свою FS или RS так, чтобы она содержала % для соответствия вашим данным, так что это еще одна причина не использовать его (в дополнение к ясности). 23.08.2014
  • Я пробовал эти решения, и они действительно работают. Сейчас все, что я действительно знаю, это RegEx, а не sed или awk. По правде говоря, я понятия не имею, как интерпретировать приведенный выше код awk. Я хотел бы действительно изучить эти инструменты, поэтому я ценю ответ на основе awk, но я отметил ответ на основе sed как ответ, потому что именно так был задан вопрос. 25.08.2014

  • 3

    sed — отличный инструмент для простых подстановок в одной строке, но для всего остального (т. е. всего, что включает в себя языковые конструкции, отличные от s, g и p с -n), просто используйте awk.

    Использование GNU awk для многосимвольных RS, границ слов \< и \> и gensub():

    $ gawk -v RS='^$' -v ORS= '{
        match($0,/\<Seven\>.*\<Fifteen\>/)
        print substr($0,1,RSTART-1) \
              gensub(/\n/," ","g",substr($0,RSTART,RLENGTH)) \
              substr($0,RSTART+RLENGTH)
    }' file
    One Two Three
    Four Five Six
    Seven Eight Nine Ten Eleven Twelve Thirteen Fourteen Fifteen
    Sixteen Seventeen Eighteen
    Nineteen Twenty Twenty-One
    

    Без преувеличения — все эти загадочные односимвольные языковые конструкции sed (N, b, a и т. д.) буквально устарели в середине 1970-х, когда был изобретен awk, и людям больше не нужно было использовать sed для многострочного редактирования.

    23.08.2014

    4

    вы также можете использовать этот метод sed

    sed '/Seven/{:loop ; N ;/\nSixteen/{p;d}; s/\n/ /g; t loop}' filename
    
    23.08.2014
    Новые материалы

    Объяснение документов 02: BERT
    BERT представил двухступенчатую структуру обучения: предварительное обучение и тонкая настройка. Во время предварительного обучения модель обучается на неразмеченных данных с помощью..

    Как проанализировать работу вашего классификатора?
    Не всегда просто знать, какие показатели использовать С развитием глубокого обучения все больше и больше людей учатся обучать свой первый классификатор. Но как только вы закончите..

    Работа с цепями Маркова, часть 4 (Машинное обучение)
    Нелинейные цепи Маркова с агрегатором и их приложения (arXiv) Автор : Бар Лайт Аннотация: Изучаются свойства подкласса случайных процессов, называемых дискретными нелинейными цепями Маркова..

    Crazy Laravel Livewire упростил мне создание электронной коммерции (панель администратора и API) [Часть 3]
    Как вы сегодня, ребята? В этой части мы создадим CRUD для данных о продукте. Думаю, в этой части я не буду слишком много делиться теорией, но чаще буду делиться своим кодом. Потому что..

    Использование машинного обучения и Python для классификации 1000 сезонов новичков MLB Hitter
    Чему может научиться машина, глядя на сезоны новичков 1000 игроков MLB? Это то, что исследует это приложение. В этом процессе мы будем использовать неконтролируемое обучение, чтобы..

    Учебные заметки: создание моего первого пакета Node.js
    Это мои обучающие заметки, когда я научился создавать свой самый первый пакет Node.js, распространяемый через npm. Оглавление Глоссарий I. Новый пакет 1.1 советы по инициализации..

    Забудьте о Matplotlib: улучшите визуализацию данных с помощью умопомрачительных функций Seaborn!
    Примечание. Эта запись в блоге предполагает базовое знакомство с Python и концепциями анализа данных. Привет, энтузиасты данных! Добро пожаловать в мой блог, где я расскажу о невероятных..


    Для любых предложений по сайту: [email protected]