Intereting Posts
Как запустить файл .desktop? Является ли перенос файлов между телефоном Android и Linux, который должен быть простой задачей? В сценарии оболочки bash пишется цикл for, который выполняет итерацию по строковым значениям Может ли cp -r заменить cp -a в этом случае? Клавиша Numlock Num Lock для функции Caps Lock Странное закрытие редактора vi Составляет ли sed запись в файл или дает образец вывода Почему правила iptables исчезают при перезагрузке моей системы Debian? Глобальный макрос «swap characters» в KDE Извлечение аудио из видео без преобразования в пользовательских действиях Thunar Как вводить текст в новый текстовый файл с помощью nano из командной строки? Первые два поля, которые будут разделены _ и остальными полями, как они есть Почтовый вывод cron я не могу открыть, ping, .. любой домен после обновления debian Как удалить последнюю строку из всех файлов из каталога?

Извлечение рисунка из нескольких строк

У меня есть файл test.tex с контентом, похожим на это:

 \documentclass{scrartcl} \usepackage{graphicx} \title{Test} \author{Author 1, Author 2, Author 3} \begin{document} \end{document} 

Я хочу извлечь каждого автора, который написан в { ... } . Поэтому я сделал следующее:

 authors=$(cat test.tex | grep '\author' | tr -d '\author' | tr -d '{' | tr -d '}' ) 

Этот код работает только для этого случая. Моя проблема в том, что

  1. там может быть [] вместо {}
  2. линия может охватывать несколько строк, например, следующий пример

\author{Author 1,

Author 2,

Author 3}

Кто-нибудь знает, как решить эти две проблемы?

 #!/bin/bash sed -nr ' /\\author/ { :ending /]|}$/! { N b ending } s/\\author(\{|\[)(.*)(}|])/\2/p } ' test.tex 

Объяснение (код тот же, но комментарии добавлены):

 #!/bin/bash sed -nr ' # if the line contains the \author string, we are working with it. /\\author/ { ##### this part are needed for multiple line pattern processing # put a label here. We will be return to this point, # until we reach line, which have } or ] in the ending. :ending # if this line does not ended by } or ]. # It is tell us, that this line continues on the next line. /]|}$/! { # Take the next line and append it to the previous line. # Just join them together. N # Go to the ":ending" label b ending } ##### ending multiple line pattern processing # remove the \author word and brackets from line s/\\author(\{|\[)(.*)(}|])/\2/p } ' test.tex 

test.tex

 \documentclass{scrartcl} \usepackage{graphicx} \title{Test} \author{Author 1, Author 2, Author 3} \author[Author 1, Author 2, Author 3] \author{Author 1, Author 2, Author 3} \author[Author 1, Author 2, Author 3] \begin{document} \end{document} 

вывод

 Author 1, Author 2, Author 3 Author 1, Author 2, Author 3 Author 1, Author 2, Author 3 Author 1, Author 2, Author 3 
 grep -zPo '\\author{\K[^}]*' ex1.tex | tr '\0\n' '\n ' 

Некоторые быстрые пояснения:

  • -z ввода и вывода («строки») разделяются с помощью NULL ( \0 ). Таким образом, полный файл TeX будет одной единственной записью.
  • -P Использовать вариант регулярного выражения Perl pcre.
  • -o выводит только ту часть записи, которая соответствует regExp.
  • \\author{\K означает левый контекст

tr '\0\n' '\n ' изменяет разделитель выходной записи (от \0 до \n ) и удаляет NewLines внутри имен ( \n до )

Это похоже на работу: egrep -o '[\[{]?Author' | sed -E 's/[\[{]//' egrep -o '[\[{]?Author' | sed -E 's/[\[{]//'

Примеры:

1)

 echo "\documentclass{scrartcl} \usepackage{graphicx} \title{Test} \author[Author 1, Author 2 Author 3 ] " | egrep -o '[\[{]?Author' | sed -E 's/[\[{]//' Author Author Author 

2)

 echo "\documentclass{scrartcl} \usepackage{graphicx} \title{Test} \author[Author 1, Author 2, Author 3] \begin{document} \end{document}" | egrep -o '[\[{]?Author' | sed -E 's/[\[{]//' Author Author Author 

3)

 echo "\documentclass{scrartcl} \usepackage{graphicx} \title{Test} \author{Author 1, Author 2, Author 3} \begin{document} \end{document}" | egrep -o '[\[{]?Author' | sed -E 's/[\[{]//' Author Author Author 

Возможно, вы можете сделать это, используя только grep и lookbehinds и еще много чего. У меня лично нет проблем с использованием трубы в sed после grep .

питон

С вашим входным файлом, указанным в вопросе, один лайнер может быть выполнен следующим образом:

 $ python -c 'import sys,re;f=open(sys.argv[1],"r");a=tuple(l for l in f.readlines() if l.startswith("\\author") );print("\n".join(re.split(", |,|{|}",a[0].strip())[1:]))' input.tex Author 1 Author 2 Author 3 

И сценарий как таковой:

 #!/usr/bin/env python import sys,re # read the doc, find the desired line line="" with open(sys.argv[1]) as f: for l in f: if l.startswith("\\author"): line=l.strip() break # split at multiple separators, get slice of that list starting since 2nd item author_list = re.split( ", |,|{|}", line )[1:] # print 1 author per line print("\n".join(author_list)) 

Ключевыми шагами являются два раза – прочитайте файл и найдите строку, которая начинается с строки \\authors , а затем разделите строку на несколько разделителей на список токенов и постройте новую строку из этого списка токенов. Я также взял на себя смелость рассмотреть возможность того, что вам, возможно, придется разделить либо на , либо ,<space> .