Спасибо! Что, если бы я хотел найти все между «one is» и «String» в «Here is a one is a String»? (sed -e 's / one is (. *) String / \ 1 /'?
user1190650 06
5
@ user1190650 Это сработает, если вы также хотите увидеть "Вот это". Вы можете проверить это: echo "Here is a one is a String" | sed -e 's/one is\(.*\)String/\1/'. Если вы просто хотите часть между «один» и «String», то вам нужно сделать регулярное выражение соответствует всей линии: sed -e 's/.*one is\(.*\)String.*/\1/'. В sed s/pattern/replacement/скажите «заменить« замену »на« шаблон »в каждой строке». Он изменит только то, что соответствует «шаблону», поэтому, если вы хотите, чтобы он заменял всю строку, вам нужно сделать так, чтобы «шаблон» соответствовал всей строке.
Брайан Кэмпбелл
9
Это прерывается, когда вводитсяHere is a String Here is a String
Джей Д.
1
Было бы здорово увидеть решение для случая: «Вот бла-бла. Строка. Вот 1, бла-бла. Строка. Вот 2, бла-бла. Строка. Вот 2, а выводится только первая подстрока между Здесь и Строкой»
Джей Ди
1
@JayD sed не поддерживает нежадное сопоставление, см. Этот вопрос для некоторых рекомендуемых альтернатив.
Брайан Кэмпбелл
180
GNU grep также может поддерживать позитивный и негативный прогноз и ретроспективный анализ: в вашем случае команда будет выглядеть так:
echo "Here is a string"| grep -o -P '(?<=Here).*(?=string)'
$ echo 'Here is a string, and Here is another string.'| grep -oP '(?<=Here).*(?=string)'# Greedy match
is a string, and Here is another
$ echo 'Here is a string, and Here is another string.'| grep -oP '(?<=Here).*?(?=string)'# Non-greedy match (Notice the '?' after '*' in .*)
is a
is another
Обратите внимание, что -Pопция GNU grep не существует во grepвключенном в * BSD или в тех, которые идут с любым SVR4 (Solaris и т. Д.). Во FreeBSD вы можете установить devel/pcreпорт, который включает pcregrep, который поддерживает PCRE (и упреждающий / отстающий). В более старых версиях OSX используется GNU grep, но в OSX Mavericks он -Pявляется производным от версии FreeBSD, которая не включает эту опцию.
ghoti
1
Привет! Как мне извлечь только отдельный контент?
Дургеш Сутар
4
Это не работает, потому что, если ваша конечная строка «строка» встречается более одного раза, она получит последнее вхождение, а не следующее .
Баттл Буткус
6
В случае Here is a string a string, оба" is a " и " is a string a "являются действительными ответами (не обращайте внимания на кавычки) в соответствии с требованиями к вопросу. Это зависит от вас, какой из них вы хотите, и тогда ответ может быть соответствующим. В любом случае, для вашего требования это сработает:echo "Here is a string a string" | grep -o -P '(?<=Here).*?(?=string)'
anishsane
2
@BND, вам необходимо включить функцию многострочного поиска pcregrep . echo $'Here is \na string' | grep -zoP '(?<=Here)(?s).*(?=string)'
анишсане
58
Принятый ответ не удаляет текст, который мог быть до Hereили после String. Это будет:
sed -e 's/.*Here\(.*\)String.*/\1/'
Основное отличие - добавление .*сразу до Hereи после String.
Ваш ответ многообещающий. Но есть одна проблема. Как я могу извлечь его в первую увиденную строку, если в одной строке есть несколько строк? Спасибо
Миан Асбат Ахмад
@MianAsbatAhmad Вы бы хотели сделать *квантификатор между Hereи Stringне жадным (или ленивым). Однако тип регулярного выражения, используемый sed, не поддерживает ленивые квантификаторы ( ?сразу после .*) в соответствии с этим вопросом Stackoverflow. Обычно для реализации ленивого квантификатора вы просто сопоставляете все, кроме токена, который вы не хотите сопоставить, но в этом случае нет только одного токена, а целой строки String.
почему этот метод такой медленный? при удалении большой html-страницы этим методом это занимает около 10 секунд.
Адам Джонс
@AdamJohns, какой метод? PCRE один? PCRE довольно сложно разобрать, но 10 секунд кажутся чрезмерными. Если вы обеспокоены, я рекомендую вам задать вопрос, включая пример кода, и посмотреть, что говорят эксперты.
ghoti
Я думаю, что это было так медленно для меня, потому что он содержал очень большой источник html файла в переменной. Когда я записал содержимое в файл, а затем проанализировал его, скорость резко возросла.
Адам Джонс
22
Через GNU awk,
$ echo "Here is a string"| awk -v FS="(Here|string)"'{print $2}'
is a
grep with -P( perl-regexp ) поддерживает параметр \K, который помогает отбросить ранее сопоставленные символы. В нашем случае ранее согласованная строка была Hereисключена из окончательного вывода.
$ echo "Here is a string"| grep -oP 'Here\K.*(?=string)'
is a
$ echo "Here is a string"| grep -oP 'Here\K(?:(?!string).)*'
is a
Если вы хотите, чтобы результат был, is aвы можете попробовать следующее:
$ echo "Here is a string"| grep -oP 'Here\s*\K.*(?=\s+string)'
is a
$ echo "Here is a string"| grep -oP 'Here\s*\K(?:(?!\s+string).)*'
is a
Это не работает для:, echo "Here is a string dfdsf Here is a string" | awk -v FS="(Here|string)" '{print $2}'он только возвращается is aвместо того, чтобы быть is a is a@Avinash Raj
alper
20
Если у вас длинный файл с множеством многострочных вхождений, полезно сначала вывести числовые строки:
Спасибо! Это единственное решение, которое сработало в моем случае (многострочный текстовый файл, а не одна строка без разрывов строк). Очевидно, чтобы не было нумерации строк, необходимо опустить -nопцию в cat.
Джеффри Лебовски
... в этом случае catможно полностью опустить; sedумеет читать файл или стандартный ввод.
Tripleee
9
Это может сработать для вас (GNU sed):
sed '/Here/!d;s//&\n/;s/.*\n//;:a;/String/bb;$!{n;ba};:b;s//\n&/;P;D' file
Это представляет каждое представление текста между двумя маркерами (в данном случае Hereи String) на новой строке и сохраняет новые строки в тексте.
У всех вышеперечисленных решений есть недостатки, когда последняя строка поиска повторяется в другом месте строки. Я решил, что лучше написать функцию bash.
function str_str {local str
str="${1#*${2}}"
str="${str%%$3*}"
echo -n "$str"}# test it ...
mystr="this is a string"
str_str "$mystr""this "" string"
$ echo "Here is a String"| sed 's/.*Here//; s/String.*//'
is a
Также работает
$ echo "Here is a StringHere is a String"| sed 's/.*Here//; s/String.*//'
is a
$ echo "Here is a StringHere is a StringHere is a StringHere is a String"| sed 's/.*Here//; s/String.*//'
is a
Это удаляет строки вместо вывода чего-то среднего. Попробуйте удалить «Hello» с помощью «is» в команде sed, и она выдаст «Hello a»
Джонатан
1
Проблема. Мои сохраненные сообщения Claws Mail упакованы следующим образом, и я пытаюсь извлечь строки темы:
Subject:[SLC38A9 lysosomal arginine sensor; mTORC1 pathway]Key molecular
link in major cell growth pathway:Findings point to new potential
therapeutic target in pancreatic cancer [mTORC1 Activator SLC38A9 IsRequired to EffluxEssentialAminoAcids from Lysosomes and UseProtein as
a Nutrient][Re:Nutrient sensor in key growth-regulating metabolic pathway
identified [Lysosomal amino acid transporter SLC38A9 signals arginine
sufficiency to mTORC1]]Message-ID:<20171019190902.18741771@VictoriasJourney.com>
[SLC38A9 lysosomal arginine sensor; mTORC1 pathway]Key molecular link in major cell growth pathway:Findings point to new potential therapeutic target in pancreatic cancer [mTORC1 Activator SLC38A9 IsRequired to EffluxEssentialAminoAcids from Lysosomes and UseProtein as a Nutrient][Re:Nutrient sensor in key growth-regulating metabolic pathway identified [Lysosomal amino acid transporter SLC38A9 signals arginine sufficiency to mTORC1]]
sed ':a;N;$!ba;s/\n/ /g' corpus/01| grep -o -P '(?<=Subject: ).*(?=Message-ID:)'
который дает
[SLC38A9 lysosomal arginine sensor; mTORC1 pathway]Key molecular link in major cell growth pathway:Findings point to new potential therapeutic target in pancreatic cancer [mTORC1 Activator SLC38A9 IsRequired to EffluxEssentialAminoAcids from Lysosomes and UseProtein as a Nutrient][Re:Nutrient sensor in key growth-regulating metabolic pathway identified [Lysosomal amino acid transporter SLC38A9 signals arginine sufficiency to mTORC1]]
[SLC38A9 lysosomal arginine sensor; mTORC1 pathway]Key molecular link in major cell growth pathway:Findings point to new potential therapeutic target in pancreatic cancer [mTORC1 Activator SLC38A9 IsRequired to EffluxEssentialAminoAcids from Lysosomes and UseProtein as a Nutrient][Re:Nutrient sensor in key growth-regulating metabolic pathway identified [Lysosomal amino acid transporter SLC38A9 signals arginine sufficiency to mTORC1]]
Here is a Here String
? ИлиI Hereby Dub Thee Sir Stringy
?sed
задаваемый вопрос - «как выделить текст между отдельными строками»; это stackoverflow.com/questions/16643288/…Ответы:
источник
echo "Here is a one is a String" | sed -e 's/one is\(.*\)String/\1/'
. Если вы просто хотите часть между «один» и «String», то вам нужно сделать регулярное выражение соответствует всей линии:sed -e 's/.*one is\(.*\)String.*/\1/'
. В seds/pattern/replacement/
скажите «заменить« замену »на« шаблон »в каждой строке». Он изменит только то, что соответствует «шаблону», поэтому, если вы хотите, чтобы он заменял всю строку, вам нужно сделать так, чтобы «шаблон» соответствовал всей строке.Here is a String Here is a String
GNU grep также может поддерживать позитивный и негативный прогноз и ретроспективный анализ: в вашем случае команда будет выглядеть так:
Если есть несколько вхождений
Here
иstring
, вы можете выбрать, хотите ли вы сопоставить с первогоHere
и последнегоstring
или сопоставить их по отдельности. В терминах регулярного выражения это называется жадным совпадением (первый случай) или нежадным совпадением (второй случай)источник
-P
опция GNU grep не существует воgrep
включенном в * BSD или в тех, которые идут с любым SVR4 (Solaris и т. Д.). Во FreeBSD вы можете установитьdevel/pcre
порт, который включаетpcregrep
, который поддерживает PCRE (и упреждающий / отстающий). В более старых версиях OSX используется GNU grep, но в OSX Mavericks он-P
является производным от версии FreeBSD, которая не включает эту опцию.Here is a string a string
, оба" is a "
и" is a string a "
являются действительными ответами (не обращайте внимания на кавычки) в соответствии с требованиями к вопросу. Это зависит от вас, какой из них вы хотите, и тогда ответ может быть соответствующим. В любом случае, для вашего требования это сработает:echo "Here is a string a string" | grep -o -P '(?<=Here).*?(?=string)'
echo $'Here is \na string' | grep -zoP '(?<=Here)(?s).*(?=string)'
Принятый ответ не удаляет текст, который мог быть до
Here
или послеString
. Это будет:Основное отличие - добавление
.*
сразу доHere
и послеString
.источник
*
квантификатор междуHere
иString
не жадным (или ленивым). Однако тип регулярного выражения, используемый sed, не поддерживает ленивые квантификаторы (?
сразу после.*
) в соответствии с этим вопросом Stackoverflow. Обычно для реализации ленивого квантификатора вы просто сопоставляете все, кроме токена, который вы не хотите сопоставить, но в этом случае нет только одного токена, а целой строкиString
..
не соответствует разрывам строки. Если вы хотите сопоставить разрывы строк, вы можете заменить.
что-то вроде[\s\s]
.Вы можете удалить строки только в Bash :
И если у вас есть GNU grep, который включает PCRE , вы можете использовать утверждение нулевой ширины:
источник
Через GNU awk,
grep with
-P
( perl-regexp ) поддерживает параметр\K
, который помогает отбросить ранее сопоставленные символы. В нашем случае ранее согласованная строка былаHere
исключена из окончательного вывода.Если вы хотите, чтобы результат был,
is a
вы можете попробовать следующее:источник
echo "Here is a string dfdsf Here is a string" | awk -v FS="(Here|string)" '{print $2}'
он только возвращаетсяis a
вместо того, чтобы бытьis a is a
@Avinash RajЕсли у вас длинный файл с множеством многострочных вхождений, полезно сначала вывести числовые строки:
источник
-n
опцию вcat
.cat
можно полностью опустить;sed
умеет читать файл или стандартный ввод.Это может сработать для вас (GNU sed):
Это представляет каждое представление текста между двумя маркерами (в данном случае
Here
иString
) на новой строке и сохраняет новые строки в тексте.источник
У всех вышеперечисленных решений есть недостатки, когда последняя строка поиска повторяется в другом месте строки. Я решил, что лучше написать функцию bash.
источник
Вы можете использовать две команды s
Также работает
источник
Чтобы понять
sed
команду, мы должны построить ее шаг за шагом.Вот ваш исходный текст
Попробуем удалить
Here
строку сs
опцией ubstition вsed
На данный момент, я полагаю , вы могли бы удалить
String
, аНо это не ваш желаемый результат.
Чтобы объединить две команды sed, используйте
-e
опциюНадеюсь это поможет
источник
Вы можете использовать
\1
(см. Http://www.grymoire.com/Unix/Sed.html#uh-4 ):Содержимое, заключенное в скобки, будет сохранено как
\1
.источник
Проблема. Мои сохраненные сообщения Claws Mail упакованы следующим образом, и я пытаюсь извлечь строки темы:
Согласно A2 в этой теме, как использовать sed / grep для извлечения текста между двумя словами? первое выражение, приведенное ниже, «работает» до тех пор, пока совпадающий текст не содержит новой строки:
Однако, несмотря на то, что я попробовал множество вариантов (
.+?; /s; ...
), я не смог заставить их работать:Решение 1.
За извлечение текста между двумя строками в разных строках
который дает
Решение 2. *
Per Как я могу заменить новую строку (\ n) с помощью sed?
заменит новые строки пробелом.
Связать это с A2 в Как использовать sed / grep для извлечения текста между двумя словами? , мы получили:
который дает
Этот вариант удаляет двойные пробелы:
дающий
источник