カットしてもカットされない場合は何を使用すればよいですか?


19

citiesこのようなファイルがあります:

[1598] San Diego, US (inactive)
[4517] St Louis, US (inactive)
[6346] Orlando, US (inactive)

私は次のように都市名を切り取りたいです。

San Diego
St Louis
Orlando

これは私が思いつくことができる最高のものです:

cut -d ',' -f1 cities | cut -d ']' -f2

しかし、それでも名前の前にスペースが残っています。cutいくつかの文字の区切り文字を受け入れるように使用できる類似のコマンドはあり]ますか?


1
tr不要な文字を削除するのに便利です。
ローレンス

人々の答えでコードを試すと、3つの異なる出力が表示されます。これは、質問が100%明確ではなかったことを示しています。「カットアウト」とは、削除または選択を意味しますか?あなたがしたいですか(inactive)ステータスがありませんか?サンプル出力を提供してください。
ミケル

@Mikel-私がcut物事を切り取るために使用していることを考えると、失敗した例の意図を見ることができますが、コンテキストではかなり明確なはずです。さらに明確にするためにサンプルを提供します。:)
キットSunde

いいえ、そうでもありません。あなたの質問の1つの文を「都市名のみを印刷する」に変更しました。これは、「カット」という単語の使用が私には不明瞭だったためです。変更は正しいですか?
ミケル

1
@Kit Sunde:サンプル出力を見ると、間違いなく理解できます。タイトルはかわいいです。「カットアウト」は、Ctrl + Xを押したときに何が起こるかを考えさせてくれるため、変更を提案したのはあなたの質問です。単純な意見の相違である場合、ダウン投票はばかげているでしょう。
ミケル

回答:


15

AwkAwk Infoも確認してください)は、この種の質問にぴったりです。試してください:

awk -F'[],] *' '{print $2}' cities

これは、フィールドセパレータ-F[],] *- として定義します。これは、閉じ角括弧またはコンマのいずれかが出現し、その後にゼロまたは任意の数のスペースが続くことを意味します。もちろん、要件に合わせて変更できます。正規表現を読んでください。

行が分割されると、分割結果を使用して必要な処理を実行できます。ここでは、でのみ2番目のフィールドを印刷することにしましたprint $2。awk命令は単一引用符で囲むことが重要です。そうしないと、シェルによって$ 2が置換されます。


2
]山括弧ではありません。山括弧は<>です。 []「角かっこ」または単に「角かっこ」です。
cjm

実際に正規表現を読み進める必要がない限り、その閉じ括弧をエスケープする必要があると思います。
キットサンデ

@cjm-たぶん彼はドイツ人です:news.ycombinator.com/item?id=1181243 :)
キットSunde

1
@cjm、すみません、角かっこを言うつもりでしたが、ちょっと速すぎました。@キット、私はドイツ人ではありません。内側の閉じ括弧をエスケープしたくない(それは意味をなさない)が、それは範囲の最初の文字でなければならない。
asoundmove

12

cutパイプラインの最後を次のように変更できます。

cut -d ' ' -f2-

上記は、フィールドセパレーターが空白であり、2番目から始まるすべてのフィールドを選択することを意味します。完全なシーケンスは次のようになります。

cut -d ',' -f1 cities | cut -d ' ' -f2-

12

より複雑な解析を行うには、sed(1)を使用する必要があります。

sed -e 's/\[[0-9]\+\] \([^,]\+\),.*/\1/' cities

または-rpepoluanが示唆するように、正規表現を単純化するために使用します

sed -re 's/\[[0-9]+\] ([^,]+),.*/\1/' cities

2
+1。あなたも大幅に正規表現パターン簡素化し、高度な正規表現の文字をエスケープ防ぐために-rを使用することができます
pepoluan

0

私は通常、sedやgrepが困難になったときにPerlを使用します。

Perlで作成する方法はいくつかあります。たとえば、高速であることを好むかもしれませんし、入力のわずかな予期しない問題を処理することを好むかもしれません(たとえば、1つが予期されていた2つのスペース)。

1つの明白な方法(idは数値、市はアルファベット、ステータスはアルファベットと仮定):

while (<>) {
    if (/^\[\d+\] (\w+(?: \w+)*), \w+ \(\w*\)$/) {
        my $city = $1;
        print "$city\n";
    }
}

または、より遅いがより寛容です(より多くのバックトラッキングを行います):

while (<>) {
    if (/^.*\]\s+(.*),.*$/) {
        my $city = $1;
        print "$city\n";
    }
}

またはより高速です(閉じ括弧の最初の出現でフィールドが停止します):

while (<>) {
    if (/^\[[^]]*\] ([^,]*), \S+ \([^)]*\)$/) {
        my $city = $1;
        print "$city\n";
    }
}

スクリプトではなくコマンドラインから、-n基本的にwhile (<>) { BLOCK }ループを追加するオプションを使用できます。

perl -ne '/^\[[^]]*\] ([^,]*), \S+ \([^)]*\)$/ and print $1, "\n";' cities

または、使用法をカットに似せたい場合-Fは、awkの-Fオプションに似たオプションを使用できます。たとえば、次のようになります。

perl -a -n -F'/[],]\s+/' -e 'print $F[1], "\n"' cities

この方法は、明らかに、フィールドに区切り文字が含まれないことを前提としています。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.