入力:
19. "foo foo" (bar bar) (19) raboof
"foo foo" raboof
期待される出力:
"foo foo" (bar bar) (19)
"foo foo"
ご覧のとおり、二重引用符と括弧を残したいと思います。
二重引用符または括弧の間にないものはすべて削除する必要があります。
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
。これで、次の2つの方法で実行できます。
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"
新しいバージョン(()
または""
の間にスペースを入れることができます):
以下の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>
assumeが存在する場合、opening文字ごとにclose文字があります:'('
および'"'
(仮定する必要があります) 、そうでない場合、ファイルが間違っているか、「ネストされた」括弧または引用符の場合、質問はより複雑なルールのセットに言及する必要があるため、以下のコードも同様に仕事をするはずです:
#!/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]))
リスト内の文字をリストします:['(', ')', '"']
、見つかった一致から2つのチャンクを作成し、各カップルの範囲にあるものを出力します。
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 ['(', ')', '"']])
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"
元のタスク :
入力:
- 「foo」(バー)(19)
raboof "foo" raboof
期待される出力:
「foo」(バー)(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
出力:
"foo" (bar) (19)
"foo"
あなた(またはこれを読んでいる同様の問題を持つ誰か)が改行を保存する必要がない場合、次のように動作します:
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$' ' \n' \
| sed 's/^ //'
最初のsed
は、すべての行の最後に$
を追加します。 (これには任意の文字を使用できます。)2番目は上記とほぼ同じgrep
ですが、行末で$
にも一致するため、すべての行末に一致します。 tr
は、改行をスペースに、ドルを改行に変換します。ただし、その前の出力にはtr
に$
があり、その後に改行があったため、その後の出力には改行があり、その後にスペースがあります。最後のsed
は、これらのスペースを取り除きます。
別の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を介したもう1つ
$ 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\""
は1つの文字列として扱われます。