изменить строки при поиске указанной строки

Если вы хотите найти все слова длиной 64 из /path/to/file, вы можете использовать

tr -c '[:alnum:]' '\n' < /path/to/file | grep '^.\{64\}$'

Это заменяет все не -буквенно-цифровые символы символами новой строки, поэтому каждое слово находится на отдельной строке. Затем он фильтрует этот результат, чтобы включить только слова длины 64.

1
05.03.2021, 22:21
6 ответов
awk '/^ABC/ && pre { print dpre ORS $0; pre=""; next }
                   { if(pre) print pre; pre=dpre=$0; sub(/ {0,4}/, "END ", dpre) }
END{ if(pre) print dpre }' infile

Первый блок будет выполняться только в том случае, если строка начинается со строкиABCи когда также была установлена ​​временная переменная pre, иначе будет выполнен следующий блок.

блок END{...}будет выполнен только один раз и после завершения всех.

для первой строки, конечно, все ещеpreпеременная еще не установлена, поэтому будет выполнен второй блок, и он делает следующее:

  • если внутри есть что-то preнапечатайте сначалаif(pre) print pre(этим мы откладываем печать предыдущей строки, чтобы проверить, начинается ли следующая строка с ABCили нет, потому что нам нужно добавить ENDвпереди этой линии)

  • затем мы копируем эту строку, скажем, в две отдельные переменные preиdpre(одна будет нетронутой (позже нам нужно напечатать ее нетронутой ), а для другой в sub(/ {0,3}/,"END ", dpre)мы добавляем ENDстрока в dpre.

    Обратите внимание, что с {0,4}(ноль или максимум 4 пробела; 4 получается из длины END<SPC>), мы гарантируем, что строка ENDвсегда будет начинаться, а также предотвращаем усечение исходного значения строки, если пробелов вообще не было.


Ниже вы можете проследить каждую итерацию команды для собственного понимания:

  • ПОВТОР
  • Прочитать строку; Это начинается с ABC(/^ABC/)?
    • нет ; затем ничего не делайте, и следующий блок будет выполнен; перейти к 2 й-Блок
    • да ; Был ли установлен pre?
      • да , тогда сделайте это
        • вывести содержимое переменной dpre, затем одну новую строку ORS, а затем саму текущую строку
        • пустая переменная pre=""и переход к REPEAT из-за оператора nextговорит об этом.
      • нет ; затем ничего не делайте, и следующий блок будет выполнен;перейти к 2 й ​​- Блок
  • 2 и-Блок
    • установлен ли pre?
      • да ; сделай это
        • print preэто установлено в "if(pre) print pre";
        • обновить текущую строку в обеих переменных pre=dpre=$0;
        • добавить перед строкойEND строку dpre.
      • нет ; сделай это
        • обновить текущую строку в обеих переменных pre=dpre=$0;
        • добавьте строкуEND для dpre.
  • если КОНЕЦ файла; вывести последнее состояние переменной dpre, если она была установлена, иначе перейти к REPEAT .
  • отделка
7
18.03.2021, 22:27
$ cat tst.awk
NF == 1 { sub(/^   /,"END",prev) }
NR > 1 { print prev }
{ prev = $0 }
END { sub(/^   /,"END",prev); print prev }

$ awk -f tst.awk file
ABC
     2   3   4
     7   9   4
END  1   2   5
ABC
     13  11  17
END  2   1   1
ABC
     7   9   14
     5   8   2
     9   9   9
END  7   1   2
3
18.03.2021, 22:27

Шаг 1:

for i in $(awk '/ABC/ {print NR-1}' filename| awk '$1 != "0"');
do
    sed -i ''$i's/.*/END &/g' filename;
done

Шаг 2:

sed '$s/.*/END &/g' filename
0
18.03.2021, 22:27

POSIX sedс отключенной автопечатью шаблонного пространства(-n)

sed -ne '
  /ABC/!{x;1!p;$!d;}
  x;1!s/^ \{0,3\}/END&/p
  ${x;/ABC/p;}
'  file
ABC
     2   3   4
     7   9   4
END  1   2   5
ABC
     13  11  17
END  2   1   1
ABC
     7   9   14
     5   8   2
     9   9   9
END  7   1   2   

Вышеприведенный код sed расширен и прокомментирован.

sed -ne '
  # if we see a non boundary line...
  /ABC/!{
    x;           # store it n retrieve prev line
    1!p;         # print the prev line if not first (obviously)
    $!d;         # printed prev so go back n read next line unless we are @eof(for which see below...)
  }
  x;                  # retrieve prev
  1!s/^ \{0,3\}/END&/p; # add marker
  ${x;/ABC/p;}
  # To account for a trailing ABC
'  file
4
18.03.2021, 22:27

Другой sedподход:

1 {                     # First line of data.
        h;              # Hold current line.
        d;              # Skip to next cycle.
}

/^ABC$/ {               # An "ABC" line.
        x;              # Swap in previous line.
        s/.../END/p;    # Add "END" at start of line & print.
        d;              # Skip to next cycle.
}

x;      # Swap current and previous lines.

# Previous line now in pattern space,
# current line in hold space.

$ {                     # Last line of data.
        p;              # Print previous line.
        g;              # Get current line from hold space.
        s/.../END/;     # Add "END" at start of line.
}

# (implicit print)

Это удерживает текущую строку в области хранения, пока не будет прочитана следующая строка. Только тогда мы узнаем, нужно ли нам добавлять ENDк строке или нет перед ее печатью. Только когда мы добираемся до самой последней строки входных данных, мы знаем, что нам нужно добавить ENDк текущей строке, и мы можем напечатать как предыдущую, так и текущую строку в одном и том же цикле.

Мой подход предполагает, что входные данные содержат по крайней мере две строки ввода и что последняя строка не ABC.

В командной строке:

sed -e '1{h;d;}' -e '/^ABC$/{x;s/.../END/p;d;}' -e 'x' -e '${p;g;s/.../END/;}'
4
18.03.2021, 22:27

Perl можно использовать в этом сценарии, и благодаря его мощным возможностям регулярных выражений он может разобраться с ним в истинном -лайнере.

perlв режиме slurp -0777с включенной автоматической печатью текущей записи -pмы проверяем все строки, за которыми следует строка ABC или eof. В обоих сценариях вставляется строка «END» в начале, перезаписывая до 3 начальных пробельных символов.

perl -0777pe '
  s/^(?!ABC)\h{0,3}(?=.*\n(?:ABC|\z))/END/mg;
' file

Изучение регулярного выражения:

  • Найдите строку, которая не начинается с ABC^(?!ABC)
  • Отсутствует до 3 пробелов (по крайней мере )в начале\h{0,3}
  • С этой точки зрения, если мы можем видеть до конца текущей строки (?=.*\n(?:ABC|\z)и оттуда на следующую строку, которая начинается с ABC или это eof.
  • Выполнить замену. Поймите, что обходные пути не потребляют данные, а служат для утверждения местоположений соответствия.
1
18.03.2021, 22:27

Теги

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