Версия в perl
, используя отрицательные форумы:
$ perl -0pe 's/\n(?!([0-9]{8}|$))//g' test.txt
20141101 server contain dump
20141101 server contain nothing {uekdmsam ikdas jwdjamc ksadkek} ssfjddkc * kdlsdlsddsfd jfkdfk
20141101 server contain dump
-0
позволяет сопоставить регекс через весь файл , и \n(? !([0-9]{8}|$))
является отрицательным обзором, означающим новую строку, за которой не следуют 8 цифр, или конец строки (которая, с -0
, будет концом файла).
le Program ru Bash:
while read LINE
do
if [[ $LINE =~ ^[0-9]{8} ]]
then
echo -ne "\n${LINE} "
else
echo -n "${LINE} "
fi
done < file.txt
в однополосной форме:
while read L; do if [[ $L =~ ^[0-9]{8} ]]; then echo -ne "\n${L} "; else echo -n "${L} "; fi done < file.txt
решение с сохранением обратной косания ( -R
) и ведущие пробелы (только IFS =
после в то время как
):
while IFS= read -r LINE
do
if [[ $LINE =~ ^[0-9]{8} ]]
then
echo
echo -nE "\n${LINE} "
else
echo -nE "${LINE} "
fi
done < file.txt
однополосная форма:
while IFS= read -r L; do if [[ $L =~ ^[0-9]{8} ]]; then echo; echo -nE "${L} "; else echo -nE "${L} "; fi done < file.text
Может быть немного проще с sed
sed -e ':1 ; N ; $!b1' -e 's/\n\+\( *[^0-9]\)/\1/g'
first part :1;N;$!b1
собрать все строки в файле, разделенные на \n
в 1.
длинная строка
вторая часть полосы символ новой линии, если она следовала за нецифровым символом с возможные промежутки между ними.
Чтобы избежать ограничения памяти (особенно для больших файлов) можно использовать:
sed -e '1{h;d}' -e '1!{/^[0-9]/!{H;d};/^[0-9]/x;$G}' -e 's/\n\+\( *[^0-9]\)/\1/g'
Или забыть сложные скрипты sed
и вспомнить, что год начинается с 2
tr '\n2' ' \n' | sed -e '1!s/^/2/' -e 1{/^$/d} -e $a
Одним из способов было бы:
$ perl -lne 's/^/\n/ if $.>1 && /^\d+/; printf "%s",$_' file
20141101 server contain dump
20141101 server contain nothing {uekdmsam ikdas jwdjamc ksadkek} ssfjddkc * kdlsdlsddsfd jfkdfk
20141101 server contain dump
Однако, это также удаляет конечную новую строку. Чтобы добавить его снова, используйте:
$ { perl -lne 's/^/\n/ if $.>1 && /^\d+/; printf "%s",$_' file; echo; } > new
-l
удалит скользящие новые строки (а также добавлять по одной к каждому вызову печати
, поэтому я использую printf
вместо этого. Затем, если текущая строка начинается с цифр (/^\d+/
) и текущий номер строки больше единицы ($.>1
, это необходимо, чтобы избежать добавления лишней пустой строки в начале), добавьте \n
в начало строки. Печать printf
распечатывает каждую строку.
Или же вы можете изменить все символы \n
на \0
, а затем снова изменить те \0
, которые стоят прямо перед строкой чисел, на \n
:
$ tr '\n' '\0' < file | perl -pe 's/\0\d+ |$/\n$&/g' | tr -d '\0'
20141101 server contain dump
20141101 server contain nothing {uekdmsam ikdas jwdjamc ksadkek} ssfjddkc * kdlsdlsddsfd jfkdfk
20141101 server contain dump
Чтобы она совпадала только со строками из 8 чисел, используйте вместо этого:
$ tr '\n' '\0' < file | perl -pe 's/\0\d{8} |$/\n$&/g' | tr -d '\0'
Попытка, делающая это использование awk:
#!/usr/bin/awk -f
{
# if the current line begins with 8 digits followed by
# 'nothing' OR the current line doesn't start with 8 digits
if (/^[0-9]{8}.*nothing/ || !/^[0-9]{8}/) {
# print current line without newline
printf "%s", $0
# feeding a 'state' variable
weird=1
}
else {
# if last line was treated in the 'if' statement
if (weird==1) {
printf "\n%s", $0
weird=0
}
else {
print # print the current line
}
}
}
END{
print # add a newline when there's no more line to treat
}
Для использования его:
chmod +x script.awk
./script.awk file.txt
Другой самый простой путь (чем мой другой ответ) использование awk и алгоритм terdon :
awk 'NR>1 && /^[0-9]{8}/{printf "%s","\n"$0;next}{printf "%s",$0}END{print}' file