Как заменить новую линию \n и предстоящий +, знак с космосом

Внутри скрипта просто export LC_ALL=C.UTF-8 в начале (сразу после строки shebang, если она есть).

(Для Cygwin вам может понадобиться export LC_ALL=c.utf8.)

После этого все команды, выполняемые скриптом, будут наследовать LC_ALL.

Если вам нужно, чтобы часть вашего скрипта была невосприимчива к изменениям локали, а часть уважала локаль (например, если вы должны вычислить, а затем напечатать некоторые значения), вам может понадобиться снять значение LC_ALL после вычисления и перед печатью. В качестве альтернативы, вы можете выбрать префикс только некоторых команд в вашем скрипте с настройкой для каждой команды.

0
12.02.2019, 15:43
5 ответов

Если файл содержит только чередующийся шаблон со строками, начинающимися с +в каждой второй строке, как в

ABC
+ DEF
foo1
+ bar1
foo2
+ bar2

Затем используйте

$ sed 'N;s/\n+  */ /' file
ABC DEF
foo1 bar1
foo2 bar2

Это просто читает строку и добавляет следующую строку (сN). Затем он заменяет новую строку, вставленную N, знак плюс и пробелы, следующие за ним, одним пробелом.


Предположим, что файл может выглядеть следующим образом: без пустых строк (пустая строка будет рассматриваться как строка без+). Первая строка может не начинаться со знака плюс, но предполагается, что последняя строка начинается со знака плюс.

ABC
+ DEF
foo1
+ bar1
+ baz1
foo2
+ bar2

Затем следующий скрипт sedпреобразует его в

ABC DEF
foo1 bar1 baz1
foo2 bar2

Скрипт:

# This is the first line
1 {
    h;      # Save the line in the hold space.
    d;      # Delete and start next cycle.
}

# This line starts with a plus sign and at least one space.
/^+  */ {
    s///;   # Delete the plus sign and the space(s).
    H;      # Append to hold space with embedded newline.
    $ !d;   # Delete and start next cycle (except for on the last line).
}

# This line of input starts a new set of lines.
# Output accumulated line.
x;          # Swap with hold space.
y/\n/ /;    # Replace all embedded newlines with spaces
            # (implicit print)

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

sed -f script.sed file

Как «один -лайнер»:

sed -e '1{h;d;}' -e '/^+  */{s///;H;$!d;}' -e 'x;y/\n/ /' file
4
28.01.2020, 02:13

С gawkили mawk, которые поддерживают использование строки или регулярного выражения для RS, все намного проще:

$ awk -vRS='\n[+]' -vORS= 1

или если вы хотите пропустить несколько пустых строк, как в примере OP:

$ awk -vRS='\n+[+]' -vORS= 1 OPs_file
ABC DEF



foo bar

Это не загрузит более одной строки в память, и не будет иметь значения, начинается ли первая строка с +.

3
28.01.2020, 02:13

Используя GNU sed, мы можем загрузить две строки в пространство шаблонов и проверить состояние границы, где они встречаются.

В случае, если мы видим, что первая строка следует за второй, начинающейся с +, или вторая является пустой строкой, мы меняем границу на пустую. Затем вернитесь и прочитайте и добавьте следующую строку в пространство шаблона. Выполните те же проверки n действий. При невыполнении вышеуказанных критериев мы печатаем только первую строку, удаляя ее из пространства шаблонов, и возвращаемся, читаем следующую строку и добавляем в пространство шаблонов. Промыть и повторить.

 $ sed -E '
      :loop
         $!N
         s/\n(\+|$)/ /
      tloop
      P;D
   ' input.txt 

 ABC   DEF   
 foo   bar
1
28.01.2020, 02:13

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

.

Метод 1

sed '/^$/d' filename|sed "s/[^A-Za-z]//g"|perl -pne "s/\n/ /g"| awk '{print $1,$2"\n"$3,$4}'

output
ABC DEF
foo bar

Второй способ

step1:

    p=`cat y.txt| sed '/^$/d'| sed "s/[^A-Za-z]//g"| awk '{print NR}'| sort -rn| sed -n '1p'`


step2:

    for ((i=1;i<=$p;i++)); do cat y.txt| sed '/^$/d'|sed -n ''$i'{p;n;p}'| sed "N;s/\n/ /g";i=$(($i+1)); done| sed "s/[^a-zA-Z]/ /g"


output
ABC   DEF
foo   bar
0
28.01.2020, 02:13

В Perl можно было просто взять весь файл и заменить <newline><plus><space>последовательности напрямую:

$ cat foo.txt
ABC
+ DEF
foo1
+ bar1
+ baz1
foo2
+ bar2
$ perl -0777 -pe 's/\n\+ ?/ /g' < foo.txt
ABC DEF
foo1 bar1 baz1
foo2 bar2

(регулярное выражение выше удаляет один необязательный пробел после плюса)

3
28.01.2020, 02:13

Теги

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