Выбор раздела файла

Выбор раздела файла

У меня есть файл, отформатированный следующим образом:

title1
        line
        line

title2
        line
        line

        line

title3
        line
        line

и я хотел бы извлечь раздел ниже title2и удалить отступ. В настоящее время я использую sed(но awkили скрипт оболочки был бы подходящим в моем контексте, к сожалению, не такие языки, как perlили python) вот так:

sed -n -e '/^title2$/,/^[a-zA-Z]/ { /^[a-zA-Z]/ d ; s/^[ \t]*// ; p }'

но это оставляет логически пустую строку в конце (логически, потому что она может содержать пробелы или табуляции). Я хочу избавиться от нее. Обратите внимание, что в части, которую нужно сохранить, могут быть другие логически пустые строки (иначе a /^[ \t]*$/ dсделал бы работу). Таким образом, я хотел бы получить такой результат:

line
line

line

Я могу сделать это с помощью дополнительного процесса sed -e '$d', но мне хотелось бы узнать, можно ли избежать этого второго процесса.

решение1

Я использовал место ожидания и в итоге получил

sed -ne '/^title2$/,/^[a-zA-Z]/ { /^title2$/ { n; h; b; } ; /^[a-zA-Z]/ d; H; x; s/[ \t]*//; P; s/.*\n//; x }'

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

решение2

  • если это «чистая» линия (без табуляции или белого цвета), удалите ее также с помощью/^$/
  • для «логического» использования пробела/^\s*$/

    sed -n -e '/^title2:/,/^[a-zA-Z]/ { /^[a-zA-Z]/ d ; /^$/ d ; s/^[ \t]*// ; p }' 
    

где

  • /^$/начало и конец строки соответствия
  • /^\s*$/сопоставить начальную строку, ноль или больше пробелов или табуляций, конец строки

решение3

sed -n '/title2/,/^\S/ { //b; /^\s*$/ { N; /\n\S/q; P; D }; s/^\s*//; p }'

Я изначально сделал это, чтобы привлечь внимание @Archemar. Я был бы очень признателен, если бы вы моглипожалуйстаответить намой комментарий в этом постекогда у вас будет время. Даже если ответ "Я не знаю". СПАСИБО.

В моей оболочке bash, по крайней мере, это работает без -e. Просто интересно, зачем это вообще нужно? И если\sили\Sне поддерживается, вы можете заменить их на [ \t]'s и [^ \t]'s соответственно.

Разбор для тех, кто был таким же невежественным, как и я, когда впервые увидел этот вопрос:

  • -nотключает автоматическую печать
  • /title2/,/^\S/диапазон для sedпоиска (от строки, в которой впервые встречается строка " title2", до следующей строки, которая начинается с символа, отличного от пробела[т.е title3.]включительно)
  • {просто означает применить вложенные команды к диапазону или шаблону, который я только что указал
    • //bпозволяет следующим командам не применяться к началу и концу диапазона.
      Более буквально, если вы сопоставляете title2или ^\Sпросто переходите к концу скрипта ( b) (обрабатываете следующую строку в файле, если таковые остались), потому что вГНУsed(БСДговорит то же самое, не уверен, есть ли какая-то другая версия sed)

      '//' повторяет последнее совпадение регулярного выражения

    • /^\s*$/соответствует «логически пустым» строкам в диапазоне.
    • {
      • N; /\n\S/q;Таким образом, если это «логически пустая» строка, Nдобавляет следующую строку в пространство шаблона, а затем, если эта следующая строка является следующим заголовком, обработка полностью прекращается ( q), поэтому ни «логически пустая» строка, ни следующий заголовок не печатаются.
      • P; DЕсли «логически пустая» строкане являетсяза которым следует следующий заголовок, затемтолькопечатается «логически пустая» строка ( P), а затемтолько«логически пустая» строка удаляется из пространства шаблона, оставляя следующую строку, которая была добавлена ​​в пространство шаблона, для Nобработки с начала скрипта ( D)
    • }
    • s/^\s*//; pубирает пробелы и табуляции в начале строки и печатает отформатированную строку
  • }

@Archemar пожалуйстаПОМОЩЬ

Связанный контент