Linux環境で文字列を操作するための多くのパッケージ(grep、awk、sed ...)があることを考慮すると、php / pregと同様の構文でキャプチャグループを抽出するソフトウェアが必要です。
おそらく最も近いかもしれませんが、grep -P
それがどのように機能するのか理解していません。
このようなことは、cat file.txt | grep -P '/something="([\w]+)"/i'
キャプチャグループ内にあるもの以上を提供するようです。
誰かが私にいくつかの実際のケースを提供できますか?私をサポートし、いくつかのバリエーションと制限事項を説明してください!
編集:どこかでこれを達成するために使用されているのを見ましたが、sed
それでも構文について少し混乱しています。
答え1
pcregrep -io1 'something="(\w+)"' myfile.txt
(-i
大文字と小文字を区別しない一致の場合、-o1
最初のキャプチャグループが印刷されます。)
GNUgrep
サポート-P
(perl互換正規表現サポートで構築されている場合)と-o
。-o
ただし、Perlツアー演算子を使用してこの問題を解決できます。
grep -iPo '(?<=something=")\w+(?=")' myfile.txt
(つまり、シーケンスに一致する正規表現文字を形成する単語ただし、後ろに)something="
が従う必要があります"
。
または、最も近いPCREを使用してください。
grep -iPo 'something="\K\w+(?=")' myfile.txt
(\K
リセットマッチひも)。
ただし、Perl正規表現を使用するには、次のものを使用することもできますperl
。
perl -C -lne 'print for /something="(\w+)"/ig' myfile.txt
GNUまたはBSDを使用すると、sed
各行の一番右の一致のみが返されます。
sed -nE 's/.*something="(\w+)".*/\1/pi' myfile.txt
移植可能(拡張正規表現サポートと大文字と小文字を区別しない一致は非標準拡張であり、すべての実装sed
でサポートされていないため):
sed -n 's/.*[sS][oO][mM][eE][tT][hH][iI][nN][gG]="\([[:alnum:]_]\{1,\}\)".*/\1/p' myfile.txt
大文字が仮定i
されますI
。これは、たとえば大文字のロケールでは、動作が以前のソリューションとは異なることを意味しi
ますİ
。
連続してすべてのアイテムを見つけるための標準/携帯用ソリューション:
awk '{while(match(tolower($0), /something="[[:alnum:]_]+"/)) {
print substr($0, RSTART+11, RLENGTH-12)
$0 = substr($0, RSTART+RLENGTH-1)}}' myfile.txt
入力に長さ(文字数)の異なる小文字バージョンのテキストが含まれていると、正しく機能しない可能性があります。
罠:
\w
[[:alnum:]_]
C / POSIX以外のロケールでの一致に関して、これらすべてのソリューション間にはいくつかの違いがあります。いずれにせよ、少なくとも下線、すべての10進数のアラビア数字、ラテン英語のアルファベット(大文字と小文字)を含める必要があります。これが必要な場合は、ロケールをCに変更してください。- 上記のように、大文字と小文字を区別しない一致は、ロケールによって大きく異なります。
a-z
対英語文字にのみ興味がある場合は、A-Z
ロケールをCに変更してください。 .
少なくとも GNU 実装では、正規表現演算子はsed
有効な文字ではないバイト列と一致しません。たとえば、UTF-8 ロケールでは、ビット 8 がセットされたシングルバイト文字セットの文字と一致しないことを意味します。つまり、sed
ソリューションが正しく機能するためには、入力ファイルで使用される文字セットがユーザーロケールの文字セットと同じである必要があります。perl
、pcregrep
GNUユーティリティは通常、ランダムな長さとランダムなバイト値を含む行を処理しますが(上記の警告に注意)、最後の改行文字の後の追加データを追加の行として処理します。これらのユーティリティの他の実装はそうではないかもしれません。上記のパターンは、入力の各行を順番に一致させます。これは、複数の入力行と一致できないことを意味します。 2行以上に渡ることができないこのようなパターンでは問題になりませんが、
something="\w+"
一般的には、パターンが複数行にまたがる可能性のあるテキストと一致するようにするには、something=".*?"
次のものが必要です。- 処理するレコードの種類を変更します。
grep --null
、sed -z
(sed
GNUのみ)、、perl -0
(awk -v RS='\0'
GNUawk
および最新バージョンのみmawk
)行の代わりにNUL区切りレコードを処理できます(改行区切りレコード)。 GNUはawk
正規表現をレコード区切り文字として使用できます(-v RS='regexp'),
perlany byte value (with
-0ooo`を使用)。 pcregrep
複数行モードがあります-M
。perl
フル入力がレコードであるフルルックモードを使用(使用-0777
)
その後、perlとpcreの場合、
.
フラグが有効になっていないと改行は一致しませんs
。たとえば、pcregrep -Mio1 '(?s)something="(.*?)"'
またはperl -C -l -0777 -ne 'print for /something="(.*?)"/gis'
- 処理するレコードの種類を変更します。
grep
との一部のバージョンには、またはバグがpcregrep
あり、正規表現エンジンには通常、正規表現のマッチングに入れることができるワークロードにデフォルトの制限があります。-z
-M
答え2
Linuxにはそれぞれ異なる機能を持ついくつかのコマンドがあります。 - あなたの使命は、特定のタスクに適したツールを見つけることです。 ;)
具体的な質問を具体的に明記しなかったため、一般的な質問として維持する必要があります。
おそらく最も簡単な方法はPerlを直接使用することです。
cat file.txt | perl -wne '/([\w]+)/i and print $1'
man grep
grepのいくつかのオプションも読んでください。
-o, --only-matching
Print only the matched (non-empty) parts of a matching line, with each such part on a separate output line.
たとえば、次のように使用できます。
cat file.txt | grep -o '\w*'
しかし、最善の方法は実際には問題によって異なります。 PHPが好きな場合は、実際にコマンドラインでPHPを使用することもできます。
答え3
これは、Perlプログラムにすべての入力行を供給/消費するためにperl
使用する別の答えに基づいています。perl -ne
プログラムには、キャプチャグループを含む正規表現を含むステートメントperl
がありif
、一致するものが見つかるとそれを印刷します。
キャプチャグループを印刷するときに改行文字を追加します。改行は、複数の一致を改行で区切るために重要です。そうしないと、すべての結果が同じ行にまとめられ、予期しない/望ましくない結果につながる可能性があります。
キャプチャリンググループに一致する複数の行を取得する場合、ほとんどの場合、最初の一致する行にのみ興味があるため、使用法はですhead -1
。
次のbash
スクリプトは、それを使用して入力ファイルを処理し、抽出された結果を変数に保存する方法を示していますvalue
。
cat file.txt # something="nice"
value=$(cat file.txt | perl -ne 'if (/something="([\w]+)"/) { print $1 . "\n" }' | head -1)
echo $value # nice