正規表現で文字列から特定の値を抽出します。

正規表現で文字列から特定の値を抽出します。

多くの例を見ましたが、これはできないようです。 grepは指定されたグループに一致する出力のみを出力できますか? たとえば、動作する必要があるように見えますが、エラーが発生したりまったく出力されません。

私がしたい:

pathname="/a/long/path/of/mine/2x02 - bar.mp4"

すべての例は、長いパス、1〜2桁の数字、x、2桁の数字、スペース、-、およびファイル名で構成されています。

02 値を解析したい。 https://regex101.com/ この場合、\d{1,2}x(\d\d) は、1 = 02 と一致する必要があることを示します。

私が知らないことは私がそうしたなら

echo "$pathname" | sed -n 's/.*\d{1,2}x\(\d\d\)/\1/p'

または

echo $pathname | grep -oP '\d{1,2}x(\d\d)'

私は何も得られませんでした。私はできます:

echo $pathname | grep -oP '(\d\d)'

しかし、場合によっては、私のように連続して他の2桁の値が出ることがあります。

/a/long/path/of/mine/12x02 - bar.mp4

この場合、上記の内容は2番目の一致を指定しないと思われるため、一致グループなどを使用できる場合は、より具体的な正規表現を優先します。 Scientific Linux 7.1のbashでこれを実行しようとしています。

答え1

grepPCRE( ) を使用するのと同様に、-P次の正規表現パターンを使用できます。

grep -Po '\d{1,2}x\K\d{2}(?= )' <<<"$pathname"
  • \d{1,2}x次の1桁または2桁の数字にx一致してから\K一致を削除します。

  • \d{2}2 つの数字が正確に一致する場合、幅 0 の前方予測パターンを使用する(?= )と、2 つの数字の後にスペースがあります。

したがって、これはあなたの要件を満たす必要があります。

例:

$ grep -Po '\d{1,2}x\K\d{2}(?= )' <<<'/a/long/path/of/mine/2x02 - bar.mp4'
02

$ grep -Po '\d{1,2}x\K\d{2}(?= )' <<<'/a/long/path/of/mine/34x12 - bar.mp4'
12

$ grep -Po '\d{1,2}x\K\d{2}(?= )' <<<'/a/long/path/of/mine/0x1 - bar.mp4'
## No match

$ grep -Po '\d{1,2}x\K\d{2}(?= )' <<<'/a/long/path/of/mine/00x1 - bar.mp4'
## No match

答え2

sedを使う

デフォルトモードでsedを使用している場合は、中かっこをエスケープする必要があります。

$ echo "$pathname" | sed -n 's/.*[[:digit:]]\{1,2\}x\([[:digit:]][[:digit:]]\).*/\1/p'
02

より良い移植性のために、次の[[:digit:]]テキストを削除するために最後に\d追加します。.*

使用grep -P

grep -P振り返り機能はサポートされていますが、振り返るテキストは固定長でなければなりません。したがって、x表示したい最初の2桁の前に1桁の数字を見つけることができます。

$ echo "$pathname" | grep -oP '(?<=\dx)(\d\d)'
02

代替パス

上記の2つの方法は代替パスにも適用されます。

$ echo '/a/long/path/of/mine/12x02 - bar.mp4' | grep -oP '(?<=\dx)(\d\d)'
02
$ echo '/a/long/path/of/mine/12x02 - bar.mp4' | sed -n 's/.*[[:digit:]]\{1,2\}x\([[:digit:]][[:digit:]]\).*/\1/p'
02

答え3

POSIXシェルのみを使用

p=$pathname
p=${p##*/}
p=${p#*x}
p=${p%% *}
echo "$p"

#or on one line
p=${pathname##*/};p=${p#*x};p=${p%% *};echo "$p"

関連情報