2017-02-14 10 views
2

Я использую bash и хотел бы применить изменения непосредственно в файле с помощью однострочного интерфейса, поэтому sed был бы идеальным.замените более двух последовательных пустых строк на две пустые строки.

Я попытался с помощью опции N СЭД, то на поиск "\ п {3}" и заменяющий, что с "\ п \ п", но это не работает ...

sed -ri 'N;N;N;N;s/^(\n){3,}$/\n\n/' ./file 

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

+0

Можете ли вы уточнить некоторые примеры входов и выходов? Как бы то ни было, я не могу сказать, хотите ли вы две пустые строки (три строки новой строки) или две новые строки (одна пустая строка) между абзацами. Пример того, что вы ожидаете, прояснит это. Благодарю. –

ответ

0

Это может работать для вас (GNU СЭД):

sed '/^$/n;//!b;:a;N;s/\n$//;ta' file 

Если текущая строка является пустой печать его и освежить в следующей строке. Если текущая строка не пуста, напечатайте ее и запустите снова. Если текущая строка пуста, удалите все пустые строки до непустой строки или конца файла.

+0

Это именно то, что я искал! для объяснения. – paicito

0

Я не уверен, что это именно то, что вы ищете, но если нет, то он должен направить вас в правильном направлении:

sed -n '/./!H;/./{x;s/\n\{3,\}//p;x;p}' 

Если строка пуста, поместите его в трюме. Если линия не пуста, обменивайтесь рисунком и удерживайте пространство, удалите ненужные строки и распечатайте прежнее пространство удержания. Затем выберите непустую строку из удержания и распечатайте ее.

1

После нескольких экспериментов я придумал следующее:

/./n  # non-empty line; just print it as normal 
N   # otherwise, append the next line 
/^\n$/D # and if it's also empty, delete the first line, and don't print yet 

Я использую GNU СЭД, который не выходит при использовании N в конце; для других реализаций вам может понадобиться $!N.

Вы можете легко настроить максимальное количество пустых строк, чтобы добавить, добавив еще \n символов в финальной команде.

Вот тест, показывающий, что он работает в начале, в середине и в конце файла:

$ echo $'\n\nabc\n\ndef\n\n\n\n\nabc\n\n\n' | sed -e '/./n;N;/^\n$/D' 

abc 

def 

abc 

$ 
+0

Это хорошая работа, но он не будет делать то, что он просил (но, возможно, именно это он и хотел). На данный момент только 1 пустая строка. Это оставляет две строки, но только одна пустая строка между ними. – Chunko

+0

thebluefox, не могли бы вы уточнить, вы попросили две пустые строки, вы имели в виду две пустые строки между другим текстом (что было бы 3 строками строки - (1 на конце непустой строки + 2 на концах двух пустых строк линии), или вы имели в виду две линии между строк, которые оставят одну пустую строку. – Chunko

+0

Я неправильно читаю «две пустые строки» как «две строки», извините. Я * думаю * вы можете просто добавить еще одну строку строки в шаблон; теперь. –

-1

Sed может быть трудно держать совместимы, в зависимости от ваших требований.Но, так как вы просто хотели один лайнер, Perl будет делать эту работу и может быть более портативными

Если вам нужны две пустые строки (3 перевода строки между текстом):

perl -p0777i -e 's/^\n{3,}/\n\n/; s/\n{4,}/\n\n\n/sg;' yourfile.txt 

Если вам нужен один пустые строки (2 между текстом символы перевода строки):

perl -p0777i -e 's/^\n{2,}/\n/; s/\n{3,}/\n\n/sg;' yourfile.txt 

Если вам нужна одна пустая строка, но не новой строки в начале файла:

perl -p0777i -e 's/^\n+//; s/\n{3,}/\n\n/sg;' yourfile.txt 

Если вы не особенно заботятся о том, Theres один или два холостых в начале файла:

perl -p0777i -e 's/\n{3,}/\n\n/sg;' yourfile.txt 

тест сценария:

#!/bin/bash 

test_contents() 
{ 
    cat <<EOF 



3 blank lines 3 linefeeds prior, expect 1 removed 
3 blank lines 4 linefeeds after, expect 1 removed 



1 blank line, 2 linefeeds after, expect no change 

2 blank line, 3 linefeeds after, expect no change 


5 blank lines, 6 linefeeds after, expect 3 removed 





3 lines to end of file, expect 1 removed 



EOF 
} 

before=$(mktemp -t test_before.XXXXXX) 
after=$(mktemp -t test_after.XXXXXX) 
sed_after=$(mktemp -t test_sed.XXXXXX) 

test_contents > "${before}" 
test_contents > "${after}" 
test_contents > "${sed_after}" 


perl -p0777i -e 's/^\n{3,}/\n\n/; s/\n{4,}/\n\n\n/sg;' "${after}" 

echo Orig: 
cat "${before}" 
echo "Diff:" 
diff -U1000 "${before}" "${after}" 

Что это делает:

-p0777  read whole files in one go 
    -i   edit files specified on commandline 
    -e   specify the edit expression 

Параметр выражения/sg
Средства:

s - treat as a whole string including newlines 
    g - keep applying the edits until no more can be done 

выход:

+ diff -U1000 /tmp/test_before.XSRHYr /tmp/test_after.mU4hLU 
--- /tmp/test_before.XSRHYr 2017-02-14 21:31:09.376110847 +1030 
+++ /tmp/test_after.mU4hLU 2017-02-14 21:31:09.379110855 +1030 
@@ -1,23 +1,17 @@ 


- 
3 blank lines 3 linefeeds prior, expect 1 removed 
3 blank lines 4 linefeeds after, expect 1 removed 


- 
1 blank line, 2 linefeeds after, expect no change 

2 blank line, 3 linefeeds after, expect no change 


5 blank lines, 6 linefeeds after, expect 3 removed 


- 
- 
- 
3 lines to end of file, expect 1 removed 


-