多くの例を見ましたが、これはできないようです。 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
grep
PCRE( ) を使用するのと同様に、-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"