Как удалить три последовательных перевода строки в правиле Makefile?

789
WilliamKF

Мне нужно найти и заменить три последовательных символа новой строки во входном файле и отфильтровать их из выходного файла для правила make-файла на Centos 4. Я использую GNU sed v4.1.2 и GNU make v3.82. Я пробовал варианты на следующих безуспешно до сих пор:

THREE_LINE_FEEDS := $(shell echo "\012\012\012")  SED_RULE := 's/'$(THREE_LINE_FEEDS)'//'  output.txt: input.txt sed -r $(SED_RULE) input.txt > output.txt 

Используя предложенный perl, я получаю эту проблему в оболочке (адаптированной из моего правила make):

> cat input.txt | perl -e '$/ = undef; _ = <>; s/\n//g; print;' > output.txt Can't modify constant item in scalar assignment at -e line 1, near "<>;" Execution of -e aborted due to compilation errors. 
2

2 ответа на вопрос

3
Thor

sed only sees one line at a time, so searching for consecutive line-feeds will not work. One way is to push all the data into the hold space, and then do the replace when all input has been gathered, e.g.:

sed -r -n ' $! { # When it is not the last line 1 { h } # Replace hold space with first line 1! { H } # Otherwise append to hold space } $ { # When last line reached H # Append it to hold space g # Replace pattern space with hold space s/\n//g # Remove all occurrences of \n p # Print pattern space } ' input.txt 

Here is a simpler option using perl, but works in the same manner:

perl -e ' $/ = undef; # Slurp mode, read whole file $_ = <>; # Read file to $_ s/\n//g; # Remove all occurrences of \n print; # Output $_ ' input.txt 

Edit

A shorter perl version suggested by Peter O.:

perl -0777 -pe 's/\n//g' input.txt 
  • -0777 enables slurp mode.
  • -p implicitly prints result.
Perl не работает, когда вставлен в мои правила makefile, смотрите обновленный вопрос выше. WilliamKF 11 лет назад 0
При использовании `$` в make-файлах они должны быть защищены, т.е. добавить туда дополнительный $ $, поэтому `perl -e '$$ / = undef; $$ _ = <>; с / \ п // г; print 'input.txt> output.txt` должен работать. Thor 11 лет назад 0
Да, понял это, но все еще не работает. Получение ошибки: Невозможно изменить постоянный элемент в скалярном присваивании в строке -e 1, рядом с "<>;" Выполнение -e прервано из-за ошибок компиляции. Можете ли вы трубить в Perl? Почему он выполняет -e? WilliamKF 11 лет назад 0
Ошибка, которую вы получаете, происходит из этого бита: `_ = <>;`, должно быть `$ _ = <>;`. Любой из `perl -e ... infile` и` cat infile | perl -e ... `работает. `-e` указывает команду, которую должен выполнить` perl`, смотрите `perlrun (1)`. Thor 11 лет назад 0
Бинго, теперь это работает, нужно было $ два раза в make-файле. WilliamKF 11 лет назад 0
`perl -0777pe 's / \ n // g'` точно такой же. `0777` переводит Perl в режим file-slurp, а` p` делает цикл чтения, который печатает Peter.O 11 лет назад 2
Хорошо, не знал о опции `-0777`. Thor 11 лет назад 0
0
WilliamKF

For those interested, here is the actual makefile rule (I couldn't get the newlines to work in the original, so used a comment to add the documentation):

# 0777 - Enables slurp mode (i.e. $/ = undef; - Slurp mode, read whole file # $_ = <>; - Read file to $_) # s/\n//g; - Remove occurrences of \n # p - Implicitly print result (i.e. print; - Output $_) output.txt: input.txt $(SED) -r $(SED_RULE) input.txt | perl -0777 -pe 's/\n//g' > output.txt 

Похожие вопросы