How хан I delete text that is NOT in quotes or parentheses?

Неудар в лунку:

19. "foo foo" (bar bar) (19) raboof
"foo foo" raboof

Expected output:

"foo foo" (bar bar) (19)
"foo foo"

Эксперт you хан see, I would like to keep the double quotes and parentheses.

Everything that is not between double quotes or parentheses should be переместите.

6
задан 25 June 2015 в 14:26

8 ответов

Используя python:

#!/usr/bin/env python2
import re, sys
with open(sys.argv[1]) as f:
    for line in f:
        parts = line.split()
        for i in parts:
            if re.search(r'^[("].*[)"]$', i):
                print i,
        print '\n'.lstrip()

Вывод:

"foo" (bar) (19) 
"foo"
  • Каждая строка читается, и части, разделенные пробелами, сохраняются в названный список parts

  • Затем при помощи re модуль search функционируйте мы нашли части, которые начинаются также " или ( и конец с также " или ).

Как работать:

Сохраните сценарий как, например. script.py. Теперь можно выполнить его двумя способами:

  • Сделайте это исполняемым файлом chmod u+x /path/to/script.py и выполненный это как /path/to/script.py /path/to/file.txt т.е. вход файл file.txt как первый аргумент. Если и сценарий и файл находятся в том же каталоге, то из того каталога ./script.py file.txt

  • Можно выполнить его, не делая его исполняемым файлом, выполнить его как python2 script.py file.txt.

Ответьте на отредактированный вопрос:

#!/usr/bin/env python2
import re, sys
with open(sys.argv[1]) as f:
    for line in f:
        print ''.join(re.findall(r'(?:(?<=\s)["(].*[")](?=\s|$)|(?<=^)["(].*[")](?=\s|$))', line))

Вывод:

"foo foo" (bar bar) (19)
"foo foo"
10
ответ дан 23 November 2019 в 07:14

Если Вы (или кто-то еще с подобной проблемой, кто читает это) не должны сохранять новые строки, следующее работало бы:

grep -Eo '"[^"]*"|\([^)]*\)'

Для входа

19. "foo foo" (bar bar) (19) raboof
"foo foo" raboof

это приводит к выводу

"foo foo"
(bar bar)
(19)
"foo foo"

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

sed 's/$/\$/' \
| grep -Eo '"[^"]*"|\([^)]*\)|\$' \
| tr '\n 

первое sed добавляет $ до конца каждой строки. (Вы могли использовать любой символ для этого.) Второе является почти тем же grep как выше, но теперь также соответствует $ в конце строки, таким образом, она соответствует каждому концу строки. Эти tr превращает новые строки в пробелы и доллары в новые строки. Но так как вывод перед тем tr имел $ сопровождаемый новой строкой, вывод после того, как будут следовать за новой строкой пространством. Финал sed избавляется от тех пробелов.

' \n' \ | sed 's/^ //'

первое sed добавляет $ до конца каждой строки. (Вы могли использовать любой символ для этого.) Второе является почти тем же grep как выше, но теперь также соответствует $ в конце строки, таким образом, она соответствует каждому концу строки. Эти tr превращает новые строки в пробелы и доллары в новые строки. Но так как вывод перед тем tr имел $ сопровождаемый новой строкой, вывод после того, как будут следовать за новой строкой пространством. Финал sed избавляется от тех пробелов.

3
ответ дан 23 November 2019 в 07:14

Как 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"
<час> <час>

, Который был исходная задача :

Вход:

  1. "нечто" (панель) (19)

raboof "нечто" raboof

Ожидаемый вывод:

"нечто" (панель) (19)

"нечто"

Используя 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

Вывод:

"foo" (bar) (19)
"foo"
3
ответ дан 23 November 2019 в 07:14

Ниже простого Python код сделает это задание.

import re
with open('file') as f:
    reg = re.compile(r'"[^"]*"|\([^)]*\)')
    for line in f:
        print(' '.join(reg.findall(line)))

И другой через Perl, который использует только regex,

$ perl -pe 's/(?:"[^"]*"|\([^)]*\))(*SKIP)(*F)|\S//g;s/^\h+|\h+$|(\h)+/\1/g' file
"foo foo" (bar bar) (19)
"foo foo"
2
ответ дан 23 November 2019 в 07:14

PHP был бы:

if (preg_match_all('/"(?:[^"\\\\]+|\\\\.)+"|\\([^)]+\\)/', $input, $matches)) {
  echo implode(' ', $matches[0]);
}

Это также правильно обрабатывает оставленные символы в заключенных в кавычки строках (например, "Test \"string\"" рассматривается как одну строку.

1
ответ дан 23 November 2019 в 07:14

Новая версия (пробелы, позволенные между () или ""):

Попробуйте ниже perl команда (кредиты: @steeldriver)

perl -ne 'printf "%s\n", join(" " , $_ =~ /["(].*?[)"]/g)'

Начальная версия (никакие пробелы между () или "")

Можно попробовать следующее perl острота:

$ perl -ne '@a=split(/\s+/, $_); for (@a) {print "$_ " if /[("].*?[)"]/ };print"\n"'  file
5
ответ дан 23 November 2019 в 07:14

Другая опция 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 ['(', ')', '"']])
4
ответ дан 23 November 2019 в 07:14

Другой perl:

$ perl -nle 'print join " ", $_ =~ /".*?"|\(.*?\)/g' file
"foo foo" (bar bar) (19)
"foo foo"
2
ответ дан 23 November 2019 в 07:14

Другие вопросы по тегам:

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