(Linux)sedコマンドで破壊的置換(大量ファイル置換)

4-3.文字列置換
TV アニメ「乙女ゲームの破滅フラグしかない悪役令嬢に転生してしまった…」第 2弾 PV/2020年4月放送開始!

アニメ「乙女ゲームの破滅フラグしかない悪役令嬢に転生してしまった…」(2020)

異世界転生物なんですが、よくある俺TUEEE系ではなくてラブコメです。
私は逆ハーレム大好物ですが、男性だけでなく、周囲の女子たちすべて主人公に夢中という、もうみんな幸せ状態がTANOSHIIII系。
異世界での自分の前世の気づき方も良かったし、主人公の恋愛において唐変木(とうへんぼく)具合が面白い。
周囲の人間にも、実は前世と近しい人もいるって設定が、まだまだ楽しめるストーリーが待ってそうで、2期も期待してます。

関連記事はコチラ
https://life-is-command.com/linux-command-beginner/

さて、破滅フラグということで、破壊置換フラグの技です。

UNIXやLinuxのコマンドはそのほとんどがフィルタとして設計されていますので、基本的には元ファイルを壊すことがありません。その設計自体は優れていると思います。

しかし場合によっては、元ファイル自体を修正する必要もあるでしょう。
sedコマンドはそのような時も使えます。

デフォルトでは、sedによるフィルタは、以下のようなテキストの流れ(ストリーム)で元テキストを壊しませんが、

sedでデフォルトの置換

old_sed_new

-iオプションを指定することで、置換結果で元テキストを置き換えることができます。

sedで破壊的な置換

old_sed_old
ではsedの-iオプションを使ってみます。まずは実験用ネタをbannerで作成します。

takk~$ banner HELLO > hello.txt
takk~$ cat hello.txt
#     # ####### #       #       #######
#     # #       #       #       #     #
#     # #       #       #       #     #
####### #####   #       #       #     #
#     # #       #       #       #     #
#     # #       #       #       #     #
#     # ####### ####### ####### #######

takk~$ 

実験用テキストhello.txtが作成できたので、これを置換してみます。
hello.txt内の#を*に置換します。

takk~$ sed 's/#/*/g' -i hello.txt
takk~$ cat hello.txt
*     * ******* *       *       *******
*     * *       *       *       *     *
*     * *       *       *       *     *
******* *****   *       *       *     *
*     * *       *       *       *     *
*     * *       *       *       *     *
*     * ******* ******* ******* *******

takk~$ 

見事に元ファイルであるhello.txtの内容が置き換わりました。

「破壊的置換」と大仰な表現ですが、大したことではないです。要するに置換なのです。
しかし、sed -iの本領が発揮されるのは置換するファイルが大量にある場合です。大量ファイルを例にしてsed -iを使ってみましょう。
例によって実験用ファイルを作成したいと思います。先ほど作ったbanner.txtはrmで消しておきます。

takk~$ rm banner.txt
takk~$ for i in `seq 100`;do r=$RANDOM;mkdir $r;banner $r>$r/$r.txt;done
takk~$ ls
10007  1384   1590   17990  22712  25681  2751   30313  31372  4152  6849  9906
10290  13886  16280  1878   23157  2578   27778  30349  31704  5096  733
10956  13939  16399  19218  23759  25891  27799  30448  31781  5337  746
11991  14051  16674  19378  24187  26045  27807  30761  32105  5609  7870
12728  14179  16717  19385  24394  26079  2816   30884  32427  5702  8370
13276  14574  17374  21226  24503  26235  28265  30940  3545   5766  8433
13511  14610  17512  22235  25287  26301  28804  30971  3743   5811  8507
13521  15117  17580  22344  25525  26495  28960  31012  3925   6274  8864
13552  15293  17841  22555  25615  27190  29792  31352  3955   6356  9871
takk~$ ls 10007
10007.txt
takk~$ cat 10007/10007.txt
   #      ###     ###     ###   #######
  ##     #   #   #   #   #   #  #    #
 # #    # #   # # #   # # #   #     #
   #    #  #  # #  #  # #  #  #    #
   #    #   # # #   # # #   # #   #
   #     #   #   #   #   #   #    #
 #####    ###     ###     ###     #

takk~$ 

ディレクトリとファイルを100個ランダムに作成しました。
番号/番号.txtという形で中身のテキストにはbannerの結果が入っています。

では、テキストファイルをすべて#から*に置換してみます。

takk~$ for i in `find -type f`;do sed 's/#/*/g' -i $i;done

これだけでよいです。確認してみます。

takk~$ cat 10007/10007.txt
   *      ***     ***     ***   *******
  **     *   *   *   *   *   *  *    *
 * *    * *   * * *   * * *   *     *
   *    *  *  * *  *  * *  *  *    *
   *    *   * * *   * * *   * *   *
   *     *   *   *   *   *   *    *
 *****    ***     ***     ***     *

takk~$

念の為grepでも確認してみます。
最初に*が存在するテキストを検索し、その後#が存在するテキストを検索しました。

takk~$ grep -r '*' * | head -20
10007/10007.txt:   *      ***     ***     ***   *******
10007/10007.txt:  **     *   *   *   *   *   *  *    *
10007/10007.txt: * *    * *   * * *   * * *   *     *
10007/10007.txt:   *    *  *  * *  *  * *  *  *    *
10007/10007.txt:   *    *   * * *   * * *   * *   *
10007/10007.txt:   *     *   *   *   *   *   *    *
10007/10007.txt: *****    ***     ***     ***     *
10290/10290.txt:   *      ***    *****   *****    ***
10290/10290.txt:  **     *   *  *     * *     *  *   *
10290/10290.txt: * *    * *   *       * *     * * *   *
10290/10290.txt:   *    *  *  *  *****   ****** *  *  *
10290/10290.txt:   *    *   * * *             * *   * *
10290/10290.txt:   *     *   *  *       *     *  *   *
10290/10290.txt: *****    ***   *******  *****    ***
10956/10956.txt:   *      ***    *****  *******  *****
10956/10956.txt:  **     *   *  *     * *       *     *
10956/10956.txt: * *    * *   * *     * *       *
10956/10956.txt:   *    *  *  *  ******  *****  ******
10956/10956.txt:   *    *   * *       *       * *     *
10956/10956.txt:   *     *   *  *     * *     * *     *
takk~$ 
takk~$ grep -r '#' *
takk~$ 

#は完全に*に置換されたようです。

コメント

タイトルとURLをコピーしました