0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

grep で検索して、sed で置換する

0
Posted at

はじめに

メモ書きなので、適当に書きます。
デザインレビューとかで、文言を修正する際、毎回 AI に頼んで修正してもらっていたのですが、

  • たまーに修正漏れや、改行・句読点での修正ミスがある
  • そもそもその程度なら Token の無駄
    • ショベルカーで釘を打つようなものなのでオーバースペックすぎる

なので、既存の、すでにあるものだけで修正してやろう、というモチベーションで以下のことをやりました。

やったこと

  1. grep コマンドで検索
  2. sed コマンドで置換

はい、これだけです。

具体的な内容

具体的にはいかのようにコマンドを作成して入力しました。

grep -rl "Before" . | xargs sed -i '' 's/Before/After/g'

Before が、検索して修正する文字列
After が、置換したい文字列です。

つまり、このコマンドは、現在いる配下のファイルをすべて検索して、Before を After に置換するというコマンドです。

そんな特殊なことはしていないです。

説明

ここからはコマンドの詳細な説明をします。

各部分の役割

grep -rl "Before" .

grepは、指定した文字列やパターンをファイルの中から検索するコマンドです。

  • -r:カレントディレクトリ以下をサブディレクトリも含めて再帰的に検索します。
  • -l:一致した行の内容ではなく、一致したファイルの名前だけを出力します(--files-with-matchesの短縮形です)。
  • "Before":検索する文字列です。
  • .:検索対象のディレクトリです。カレントディレクトリを指します。

つまりこの部分は、「Before」という文字列を含むファイルの一覧を、パス名のリストとして出力します。

xargs

xargsは、標準入力から受け取った文字列を、後続のコマンドの引数として渡すコマンドです。

grep -rlが出力したファイル名の一覧を、次のsedコマンドの引数として一つずつ渡す役割を担っています。

sed -i '' 's/Before/After/g'

sedは、テキストの置換や編集を行うコマンドです。

  • -i '':ファイルを直接書き換えます(in-place編集)。空文字列''はバックアップファイルの拡張子を指定する引数で、ここでは空にすることでバックアップを作成しない指定になっています。
  • 's/Before/After/g':置換の指示です。s/検索文字列/置換文字列/フラグという形式で、g(global)フラグにより、1行の中に複数の「Before」があってもすべて置換します。

注意すべき点

macOSとLinuxで書き方が異なります

-i ''という書き方は、macOSなどに搭載されているBSD版のsed向けの書き方です。

Linuxで標準的なGNU版のsedでは、-iの直後にスペースを空けずに拡張子を書く仕様のため、-i ''と書くと空文字列''が拡張子ではなく次の引数として解釈され、エラーになるか意図しない動作になります。GNU版で同じ動作(バックアップなしの直接編集)をさせたい場合は、次のように書きます。

xargs sed -i 's/Before/After/g'

環境によって挙動が変わる点のため、実行環境がmacOSかLinuxかを確認しておくと安全です。

ファイル名にスペースが含まれると壊れます

grep -rlの出力を素のxargsに渡すと、ファイル名にスペースや改行が含まれる場合、1つのファイル名が複数の引数に分割されてしまう可能性があります。次のように-print0相当の区切り文字(NUL文字)を使う書き方のほうが安全です。

grep -rlZ "Before" . | xargs -0 sed -i 's/Before/After/g'

検索範囲が広すぎる可能性があります

.を対象にすると、.gitディレクトリの内部ファイルやnode_modulesなども検索・置換の対象に含まれます。バイナリファイルやGit管理下の内部データまで書き換えてしまう恐れがあるため、意図しないディレクトリを--exclude-dirで除外することをおすすめします。

grep -rl "Before" --exclude-dir={.git,node_modules} . | xargs sed -i 's/Before/After/g'

バックアップが残りません

-i ''(またはGNU版の-iのみ)は、置換前のファイルを保存しません。Gitで管理しているリポジトリであれば、実行後にgit diffで変更内容を確認してからコミットする、という手順を踏むと安心です。

さいごに

もっとこうした方が効率良い場合はコメントで教えていただけるとありがたいです!
また、「ここ間違ってる」があれば修正リクエストを送ってください。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?