Извлеките абзац, разделенный знаком ***, с помощью AWK

Это было некоторое время, так как я оставил minimalisting менеджеры окон как fluxbox/openbox и такой, но здесь являюсь некоторыми подсказками, которые я вспоминаю:

  1. Можно на самом деле видеть, какой код клавиши определенное сочетание клавиш повышается с помощью xev (1)

  2. Можно использовать использование xmodmap (1) для привязки определенных кодов клавиши с X событиями.

Посмотрите взгляд на страницы справочника для xev и xmodmap ;)

3
10.06.2015, 20:05
4 ответа

Укажите awk, что нужно печатать между двумя разделителями. В частности:

awk '/\*{4,}/,/<np>/' file

Это также напечатает строки, содержащие разделители, поэтому вы можете удалить их с помощью:

awk '/\*{4,}/,/<np>/' file | tail -n +2 | head -n -1

В качестве альтернативы вы можете установить для переменной значение true, если строка соответствует 1-му разделителю, и значение false, если оно соответствует второму и печатать только тогда, когда оно истинно:

awk '/\*{4,}/{a=1; next}/<np>/{a=0}(a==1){print}' file

Приведенная выше команда установит a в 1, если текущая строка соответствует 4 или более * , а также перейдет к следующему строка. Это означает, что строка *** никогда не будет напечатана.


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

Прежде всего, вам не нужна FS (разделитель полей), вы хотите RS (разделитель записей). Затем, чтобы передать литерал * , вам нужно дважды экранировать его. Один раз для экранирования * и один раз для экранирования обратной косой черты (в противном случае awk попытается сопоставить его так же, как \ r или \ t ). Затем вы печатаете вторую «строку»:

$ awk -vRS='\\*\\*\\*' 'NR==2' file

thingsIwantToRead1   
thingsIwantToRead2   
thingsIwantToRead3  

Чтобы избежать пустых строк вокруг вывода, используйте:

$ awk -vRS='\n\\*\\*\\*\n' 'NR==2' file
thingsIwantToRead1   
thingsIwantToRead2   
thingsIwantToRead3  

Обратите внимание, что здесь предполагается *** после каждого абзаца. , а не только после первого, как вы показываете.

6
27.01.2020, 21:07

В дополнение к ответу @ Terdon с AWK (и SED) вы можете использовать диапазон диапазона:

awk '/sep1/,/sep2/{print}' file

или

sed -n '/sep1/,/sep2/p' file

будет напечатать все (в том числе) SEP1 и SEP2 Отказ То есть:

~$ awk '/sep1/,/sep2/{print}' file
sep1
thingsIwantToRead1
thingsIwantToRead2
thingsIwantToRead3
sep2

В вашем случае:

~$ awk '/\*\*\*/,/^$/{print}' file
***
thingsIwantToRead1
thingsIwantToRead2
thingsIwantToRead3
 

Тогда вы можете удалить первую и последнюю строку.

Например, с:

~$ sed -n '/\*\*\*/,/^$/p' file | sed '1d;$d'
thingsIwantToRead1
thingsIwantToRead2
thingsIwantToRead3

или

~$ awk '/\*\*\*/,/^$/{print}' file | awk 'NR>1&&!/^$/ {print}'
thingsIwantToRead1
thingsIwantToRead2
thingsIwantToRead3

, если ваш абзац не слишком длинный.

6
27.01.2020, 21:07

Обновленная версия на основе редактирования вопроса:

Используя Perl:

< inputfile perl -0777 -pe 's/.*[*]+\n(.*) <np>\n.*/$1/s' > outputfile
  • <входной файл: перенаправляет содержимое входного файла inputfile на perl stdin
  • -0777: заставляет Perl вывести строки
  • -e сразу по всему файлу, а не строку за строкой
  • -p: заставляет Perl вывести строки
  • -e: заставляет Perl читать строку программы из аргументов
  • > outputfile: перенаправляет содержимое perl's stdout в outputfile

Regex breakdown:

  • s: утверждает, что выполняет подстановку
  • /: запускает шаблон поиска
  • . *[*]+\n: совпадает любое количество любого символа до конца строки, заканчивающейся одним или более * символом, за которым сразу следует символ новой строки
  • (.*) : совпадает и группирует любое количество любого символа до любого символа, за которым сразу же следует \n строка
  • . *: совпадает с любым количеством любого символа
  • /: останавливает шаблон поиска / начинает замену шаблона
  • $1: заменяет на захваченную группу
  • /: останавливает замену шаблона / начинает замену модификаторов
  • s: утверждает, что рассматривает входную строку как единую строку, заставляя . также для сопоставления символов новой строки

Вывод образца:

~/tmp$ cat inputfile
13.2000000000     , 3*0.00000000000       ,  11.6500000000     , 3*0.00000000000       ,  17.8800000000

Blablabla

  SATELLITE EPHEMERIS
     ===================
Output frame: Mean of J2000

       Epoch                  A            E            I           RA           AofP          TA      Flight Ang
*****************************************************************************************************************
2012/10/01 00:00:00.000     6998.239     0.001233     97.95558     77.41733     89.98551    290.75808    359.93398
2012/10/01 00:05:00.000     6993.163     0.001168     97.95869     77.41920    124.72698    274.57362    359.93327
2012/10/01 00:10:00.000     6987.347     0.001004     97.96219     77.42327    170.94020    246.92395    359.94706
2012/10/01 00:15:00.000     6983.173     0.000893     97.96468     77.42930    224.76158    211.67042    359.97311
 <np>
 ----------------
 Predicted Orbit:
 ----------------

 Blablabla
~/tmp$ < inputfile perl -0777 -pe 's/.*[*]+\n(.*) <np>\n.*/$1/s'
2012/10/01 00:00:00.000     6998.239     0.001233     97.95558     77.41733     89.98551    290.75808    359.93398
2012/10/01 00:05:00.000     6993.163     0.001168     97.95869     77.41920    124.72698    274.57362    359.93327
2012/10/01 00:10:00.000     6987.347     0.001004     97.96219     77.42327    170.94020    246.92395    359.94706
2012/10/01 00:15:00.000     6983.173     0.000893     97.96468     77.42930    224.76158    211.67042    359.97311
~/tmp$ 

Original version:

Using Perl:

< inputfile perl -0777 -pe 's/.*[*]{3}\n(.*\n)\n.*/$1/s' > outputfile
  • < inputfile: перенаправляет содержимое входного файла на perl stdin
  • -0777: заставляет Perl замять весь файл сразу, а не строку за строкой
  • -p: заставляет Perl выводить строки
  • -e: заставляет Perl читать строку программы из аргументов
  • > выходного файла: перенаправляет содержимое perl's stdout в outputfile

Regex breakdown:

  • s: утверждает, что выполняет подстановку
  • /: запускает шаблон поиска
  • . *[*]{3}\n: совпадает любое количество любого символа до конца строки ***\n string
  • (.*\n)\n: совпадает и группирует любое количество любого символа до символа новой строки, за которым сразу следует символ новой строки
  • . *: совпадает с любым количеством любого символа
  • /: останавливает шаблон поиска / запускает шаблон замены
  • $1: заменяет на захваченную группу
  • /: останавливает шаблон замены / запускает модификаторы
  • s: утверждает, что входная строка рассматривается как одна строка, заставляя . также для согласования символов новой строки

: выходной сигнал образца:

~/tmp$ cat inputfile
blablabla
blablabla
***
thingsIwantToRead1
thingsIwantToRead2
thingsIwantToRead3

blablabla
blablabla
~/tmp$ < inputfile perl -0777 -pe 's/.*[*]{3}\n(.*\n)\n.*/$1/s'
thingsIwantToRead1
thingsIwantToRead2
thingsIwantToRead3
~/tmp$ 
1
27.01.2020, 21:07

С sed есть два пути. Вы можете выбрать включительно или исключительно. В вашем случае выбор включительно означает печать всех строк, начинающихся с совпадения по '^*\*\*' до одной из ^ * (что бы это ни было) или ^$ пустой строки.

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

Выбор эксклюзивный работает противоположным образом. Он определяет от остановить печать до здесь до начать печать после здесь. Для вашего примера данных - и позволяя остановить печать до здесь, который будет соответствовать любой из пустых строк или , что вещь:

sed -e 'x;/^\( *<np>.*\)*$/,/^*\** *$/c\' -e '' <infile >outfile
  • x
    • Меняет местами пробелы удержания и шаблона. Это устанавливает look-behind - sed всегда на одну строку позади ввода - и первая строка всегда пустая.
  • /^\( *.*\)*$/
    • Это выбирает stop printing before here строку, которая совпадает от начала до конца с нулем или более вхождений в группе совпадений. Два типа строк могут соответствовать нулю или более вхождений - либо пустая строка, либо строка с любым количеством <пробелов> в начале строки, за которой следует строка .
  • /^*\** *$/
    • Выбирается строка начать печать после здесь, которая открывается хотя бы одним символом * звездочки и продолжается до конца строки с нулем или более вхождений * звездочки и, возможно, закрывается любым количеством пробелов.
  • c\' -e ''
    • Это cпереводит весь заблокированный выбор в одну пустую строку, сжимая все ненужные строки до строки EOF.

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


2012/10/01 00:00:00.000     6998.239     0.001233     97.95558     77.41733     89.98551    290.75808    359.93398
2012/10/01 00:05:00.000     6993.163     0.001168     97.95869     77.41920    124.72698    274.57362    359.93327
2012/10/01 00:10:00.000     6987.347     0.001004     97.96219     77.42327    170.94020    246.92395    359.94706
2012/10/01 00:15:00.000     6983.173     0.000893     97.96468     77.42930    224.76158    211.67042    359.97311 

Это предполагает, что вы хотите обрабатывать любое количество вхождений шаблона параграфа во входных данных. Если вам нужен только первый, однако, при условии, что у вас есть GNU grep и что infile является обычным, lseekable файлом:

{   grep -xm1 '*\** *'        >&2
    sed -n '/^\( *<np>.*\)*$/q;p'
}   <infile 2>/dev/null >outfile

... будет работать также.

И на самом деле, я полагаю, есть три способа. Третий может выглядеть так:

sed 'H;$!d;x;s/\(\n\*\** *\n\(\([0-9./: ]*\n\)*\)\)*./\2/g'

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

4
27.01.2020, 21:07

Теги

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