Вход:
19. "foo foo" (bar bar) (19) raboof
"foo foo" raboof
Ожидаемый результат:
"foo foo" (bar bar) (19)
"foo foo"
Как вы можете видеть, я хотел бы сохранить двойные кавычки и круглые скобки.
] Все, что не находится между двойными кавычками или круглыми скобками, должно быть удалено.
Новая версия (пробелы между () или ""):
Попробуйте выполнить команду perl (кредиты: @steeldriver)
perl -ne 'printf "%s\n", join(" " , $_ =~ /["(].*?[)"]/g)'
Новая версия (без пробелов между () или "")
Вы можете попробовать следующее perl oneliner:
$ perl -ne '@a=split(/\s+/, $_); for (@a) {print "$_ " if /[("].*?[)"]/ };print"\n"' file
Еще одна опция python:
#!/usr/bin/env python3
import sys
match = lambda ch1, ch2, w: all([w.startswith(ch1), w.endswith(ch2)])
for l in open(sys.argv[1]).read().splitlines():
matches = [w for w in l.split() if any([match("(", ")", w), match('"', '"', w)])]
print((" ").join(matches))
Скопируйте сценарий в пустой файл, сохраните скрипт как filter.py Запустите его с помощью команды: python3 /path/to/filter.py <file>
Если мы предположим, что на каждом начальном символе есть символ закрытия: '(' и '"' (мы должны предположить, что, поскольку иначе либо файл был бы неправильным, либо вопрос следует упомянуть более сложный набор правил в случае «вложенных» круглых скобок или кавычек), следующий код должен также выполнить задание:
#!/usr/bin/env python3
import sys
chunks = lambda l: [l[i:i + 2] for i in range(0, len(l), 2)]
for l in open(sys.argv[1]).read().splitlines():
words = chunks([i for i in range(len(l)) if l[i] in ['(', ')', '"']])
print((" ").join([l[w[0]:w[1]+1] for w in words]))
В нем перечислены символы в списке: ['(', ')', '"'], делает куски двух из найденных совпадений и печатает то, что находится в диапазоне каждой пары:
19. "foo" (bar bar) (blub blub blub blub) (19) raboof
"foo" raboof
выдает:
"foo" (bar bar) (blub blub blub blub) (19)
"foo"
Использование в точности как и первый скрипт.
Более или менее «триггеры» можно легко добавить, добавив в список обе стороны (начальный и конечный символ строки или раздела «сохранить»):
['(', ')', '"']
в строке:
words = chunks([i for i in range(len(l)) if l[i] in ['(', ')', '"']])
Если вы (или кто-то другой с аналогичной проблемой, кто читает это), не должны сохранять символы новой строки, будет работать следующее:
grep -Eo '"[^"]*"|\([^)]*\)'
Для ввода
19. "foo foo" (bar bar) (19) raboof
"foo foo" raboof
он дает выход
"foo foo"
(bar bar)
(19)
"foo foo"
Если вам нужны новые строки, вы можете использовать некоторые трюки, например this:
sed 's/$/\$/' \
| grep -Eo '"[^"]*"|\([^)]*\)|\$$' \
| tr '\n$' ' \n' \
| sed 's/^ //'
Первый sed добавляет $ в конец каждой строки. (Вы можете использовать любой символ для этого.) Второй почти тот же grep, что и выше, но теперь также совпадает с $ в конце строки, поэтому он соответствует каждому концу строки. [F9] превращает новые строки в пробелы и доллары в новые строки. Но так как на выходе до tr было $, за которым следует новая строка, на выходе после будет новая строка, за которой следует пробел. Финал sed избавляется от этих пространств.
Как скрипт perl:
$filename=$ARGV[0];
if (open(my $fh, '<:encoding(UTF-8)', $filename)) {
while (my $match = <$fh>) {
while ($match =~ /((\(.*?[^)]\))|(".*?"))/g) {
print "$1 ";
}
print "\n"
}
}
Или как perl однострочный:
perl -ne 'while (/((\(.*?[^)]\))|(".*?"))/g) {print "$1 ";} print "\n"' file
Выход
"foo foo" (bar bar) (19)
"foo foo"
[ ! d4] Это была оригинальная задача:
Вход: «foo» (bar) (19) raboof «foo» raboof Ожидаемый результат: «foo» (bar ) (19) «foo»Используя perl:
perl -pe '@elements=( split (/\s/) );
for $element (@elements) {
if ($element!~/^"|\(/ and $element!~/"|\($/) {
s/$element//
}
s/^\s+//;
s/\s+$/\n/
};' file
или как однострочный:
perl -pe '@elements=( split (/\s/) ); for $element (@elements) { if ($element!~/^"|\(/ and $element!~/"|\($/) { s/$element// } s/^\s+//; s/\s+$/\n/ };' file
Выход [ ! d3]
"foo" (bar) (19)
"foo"
Другой perl:
$ perl -nle 'print join " ", $_ =~ /".*?"|\(.*?\)/g' file
"foo foo" (bar bar) (19)
"foo foo"
Ниже простого кода python будет выполняться это задание.
import re
with open('file') as f:
reg = re.compile(r'"[^"]*"|\([^)]*\)')
for line in f:
print(' '.join(reg.findall(line)))
И еще один через Perl, который использует только регулярное выражение,
$ perl -pe 's/(?:"[^"]*"|\([^)]*\))(*SKIP)(*F)|\S//g;s/^\h+|\h+$|(\h)+/\1/g' file
"foo foo" (bar bar) (19)
"foo foo"
PHP будет:
if (preg_match_all('/"(?:[^"\\\\]+|\\\\.)+"|\\([^)]+\\)/', $input, $matches)) {
echo implode(' ', $matches[0]);
}
Это также корректно обрабатывает экранированные символы внутри цитируемых строк (например, "Test \"string\"" рассматривается как одна строка.