私のBashスクリプトでPerl正規表現が機能しないのはなぜですか? MacOS端末

私のBashスクリプトでPerl正規表現が機能しないのはなぜですか? MacOS端末

私は仕事でAppleScriptsのワークフローを捨て、バックグラウンドで実行できるより簡単なものを作成したいと思います。これを行うには、毎晩35〜40ファイル(7〜8ファイルの5つの品質バージョン)を受け取り、ファイル名の一部を抽出する必要があります。

たとえば、これらのファイルの配置(省略)は次のとおりです。

各ファイルには5つのバージョンがあります。

    ab_12_345_01_dest_xxxxxxxxxx_640x360_1000.jpg
    ab_12_345_01_dest_xxxxxxxxxx_768x432_3000.jpg
    ab_12_345_01_dest_xxxxxxxxxx_960x540_5000.jpg
    ab_12_345_01_dest_xxxxxxxxxx_1280x720_7000.jpg
    ab_12_345_01_dest_xxxxxxxxxx_1920x1080_9000.jpg

ファイル名はすべて次のとおりです(最も高いバージョンを使用します。理由は後で説明します)。

    ab_12_345_01_dest_xxxxxxxxxx_1920x1080_9000.jpg
    ab_12_345_02_dest_yyyyyyyyyy_1920x1080_9000.jpg
    ab_12_345_03_dest_zzzzzzzzzz_1920x1080_9000.jpg
    ab_12_345_part1_aaaaaaaaaa_1920x1080_9000.jpg
    ab_12_345_part2_bbbbbbbbbb_1920x1080_9000.jpg
    ab_12_345_part3_special_cccccccccc_1920x1080_9000.jpg
    ab_12_345_part4_dddddddddd_1920x1080_9000.jpg
    ab_12_345_04_dest_special_eeeeeeeeee_1920x1080_9000.jpg

したがって、私の目標は、ファイル名の一部を使用して9000各ファイルの最上位バージョンのみをgrepしてから(コピーするのに最も長い時間がかかるため、そのファイルがある場合は残りのファイルもそこにあります)、すべてを2番目のバージョンまで抽出することですです。最後_。これまでの最初の部分を完了できましたが、2番目の部分は完了できませんでした。

これにより、最も高いバージョンのリストのみが表示されます。

    $ ls | grep 9000
    ab_12_345_01_dest_xxxxxxxxxx_1920x1080_9000.jpg
    ab_12_345_02_dest_yyyyyyyyyy_1920x1080_9000.jpg
    ab_12_345_03_dest_zzzzzzzzzz_1920x1080_9000.jpg
    ab_12_345_part1_aaaaaaaaaa_1920x1080_9000.jpg
    ab_12_345_part2_bbbbbbbbbb_1920x1080_9000.jpg
    ab_12_345_part3_special_cccccccccc_1920x1080_9000.jpg
    ab_12_345_part4_dddddddddd_1920x1080_9000.jpg
    ab_12_345_04_dest_special_eeeeeeeeee_1920x1080_9000.jpg

ls | grep 9000 | perl -pe '/^.+(?=_.+_.+)/mgそれから私は次のことを得ることを考えてみました(私はオンラインのすべてのRegExテスター、特に私が見つけることができるPerl RegExテスターがうまくいくと言ったことに基づいています)。

    $ ls | grep 9000 | perl -pe '/^.+(?=_.+_.+)/mg`
    ab_12_345_01_dest_xxxxxxxxxx
    ab_12_345_02_dest_yyyyyyyyyy
    ab_12_345_03_dest_zzzzzzzzzz
    ab_12_345_part1_aaaaaaaaaa
    ab_12_345_part2_bbbbbbbbbb
    ab_12_345_part3_special_cccccccccc
    ab_12_345_part4_dddddddddd
    ab_12_345_04_dest_special_eeeeeeeeee

しかし、Perlでパイプしたことがないように、同じ結果が得られました。最初はこれを達成するためにawkを使用しようとしましたが、入力したコマンドがかなり長くなっているため、RegExを使用することをお勧めします。ただし、(文字列の先頭から計算する_代わりに)2番目の最後の位置で一致を停止して.awkを設定すると、awkが最後の位置を維持するために肯定的な予測が必要になります。___{$NL=$(NL-1)=""; print $0}

ベストアンサー1

オプションperlがあるため、コマンドを使用すると常にその行を印刷できます。-p一致する部分は何もしません。

一致する部分が必要で-n印刷します。

ls -1 *9000.jpg \
| perl -lne 'print $1 if /^(.+)(?=_.+_.+)/'

ファイル名に改行文字が含まれている可能性があるため、ゼロで区切られたファイル名を読み取るように変更する必要がありますが、あなたの場合は必要ありません。

printf '%s\0' *9000.jpg \
| perl -lne 'INIT{ $/ = "\0"}; print $1 if /^(.+)(?=_.+_.+)/'

あるいは、forループからファイル名を読み取ってから、シェル引数拡張を使用することもできます。

for f in *9000.jpg; do printf '%s\n' "${f%_*_*}"; done

これはあなたの仕事に適しているかもしれません。 (=>「ファイル名に行ベースのテキスト編集ツールを使用しないでください。」@Kusalananda)

おすすめ記事