プレーンbashで正規表現を使用して部分文字列を抽出する


97

bashを使用して文字列から時間を抽出しようとしていますが、それを理解するのに苦労しています。

私の文字列は次のとおりです:

US/Central - 10:26 PM (CST)

そして、その10:26部分を抽出したいと思います。

誰もがbashでのみこれを行う方法を知っています-sed、awkなどを使用せずに?

のように、私はPHPで使用します-最善の方法ではありませんが、それは機能します-のようなもの:

preg_match( ""(\d{2}\:\d{2}) PM \(CST\)"", "US/Central - 10:26 PM (CST)", $matches );

回答にsedまたはawkを使用している場合でも、助けてくれてありがとう

回答:


207

純粋な

$ cat file.txt
US/Central - 10:26 PM (CST)
$ while read a b time x; do [[ $b == - ]] && echo $time; done < file.txt

bash正規表現を使用した別のソリューション:

$ [[ "US/Central - 10:26 PM (CST)" =~ -[[:space:]]*([0-9]{2}:[0-9]{2}) ]] &&
    echo ${BASH_REMATCH[1]}

grep高度な正規表現を使用して見回す別のソリューション:

$ echo "US/Central - 10:26 PM (CST)" | grep -oP "\-\s+\K\d{2}:\d{2}"

sedを使用した別のソリューション:

$ echo "US/Central - 10:26 PM (CST)" |
    sed 's/.*\- *\([0-9]\{2\}:[0-9]\{2\}\).*/\1/'

perlを使用した別のソリューション:

$ echo "US/Central - 10:26 PM (CST)" |
    perl -lne 'print $& if /\-\s+\K\d{2}:\d{2}/'

そして最後にawkを使用します:

$ echo "US/Central - 10:26 PM (CST)" |
    awk '{for (i=0; i<=NF; i++){if ($i == "-"){print $(i+1);exit}}}'

涼しい!パターンでハイフン「-」も使用する可能性はありますか?そのgrepはいくつかの一致を返すので、私はハイフン、スペース、時間の順になっているものだけに関心があります...
andrux

私はおそらくperlソリューションを手に入れることができましたが、それは素晴らしいプラスです。ありがとう!
andrux

楽しみのためにawk oneを追加=)
Gilles Quenot 2012年

1
\ K "トリック"を教えてくれてありがとう。Perl構文を使ったgrepは本当に強力です。
Marco Sulla

1
私はsedバージョンが好きですsedが、必ずしも+修飾子をとらない他の人に警告したいと思いました。回避{1, }策の1つは、修飾子を使用して1つ以上に一致させることです。
CodeBrew

89
    echo "US/Central - 10:26 PM (CST)" | sed -n "s/^.*-\s*\(\S*\).*$/\1/p"

-n      suppress printing
s       substitute
^.*     anything at the beginning
-       up until the dash
\s*     any space characters (any whitespace character)
\(      start capture group
\S*     any non-space characters
\)      end capture group
.*$     anything at the end
\1      substitute 1st capture group for everything on line
p       print it

8
これが私に一瞬のsedマスターになった気がします。調整できる1つの良いオプションは、理解できない9つのオプションよりも優れています。
Noumenon 2017年

詳細な説明をありがとう、今後の「XXXXの正規表現方法」の投稿を回避するのに役立ちます。
studgeek 2017

4
最初に印刷を抑制し-n、次に再度印刷を要求する理由を説明していただけます/pか?-nフラグを省略して/pディレクティブを省略することは同じではないでしょうか?ありがとう。
Victor Zamanian 2017

すばらしい答えです!助けてくれてありがとう:-)
ブルーノ・ラビット

1
ここから@VictorZamanian : "デフォルトでは、sedはすべての行を出力します。置換すると、古いテキストの代わりに新しいテキストが出力されます。sedにオプションの引数を使用すると、" sed -n "は出力されません。デフォルトでは、すべての新しい行を印刷します。「-n」オプションを使用すると、「p」フラグを使用すると、変更された行が印刷されます。
tdashroy

26

Quick 'n dirty、regex-free、low-robustness chop-chopテクニック

string="US/Central - 10:26 PM (CST)"
etime="${string% [AP]M*}"
etime="${etime#* - }"

5
嫌なほど汚いので自分で考えなかったのは恥ずかしいです。+1 | read zone dash time apm zoneも機能
Orwellophile 2015

非常にクリーンで、外部プログラムの呼び出しを回避します。
Victor Zamanian 2017

8
こんにちは、これは、人々が立ち去ってより多くの研究を行えるように、技術に関するさらなるドキュメントまたはいくつかの名前への参照が含まれている場合、10倍より有用です。興味のある方は、これはbash文字列操作です。詳細については、こちらをご覧ください。tldp.org
Pedro Mata-Mouros

0

あなたの文字列が

foo="US/Central - 10:26 PM (CST)"

その後

echo "${foo}" | cut -d ' ' -f3

仕事をします。


1
またはcut -c14-18もちろん、文字の位置が変化しない限りだけです。これは、タイムゾーンが固定されている場合は発生しません。
マーカス

サー・クエスチョンはカットではなく正規表現を求められます
indrajit narvekar
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.