web-dev-qa-db-ja.com

sedコマンドでファイル名を使用するにはどうすればよいですか?

異なるファイル名を除いて、同じディレクトリに同じ.confファイルがいくつかあります。一意の名前を持つ.confファイルごとに、ファイル内の文字セットをファイル名に置き換えたいと思います。例えば:

現在、すべてのファイルで:

datafname = example.nex
ofprefix = best.example

理想的な出力:

ファイル名:25.conf

datafname = 25.nex
ofprefix = best.25

ファイル名:26.conf

datafname = 26.nex
ofprefix = best.26

sedを使用してこれらすべてのファイルを検索し、次のような方法でテキスト文字列を検索してファイル名に置き換えることができると考えました。

sed -i conf 's/example/echo $f/g' *

しかし、これは適切に機能していません。誰もこれを行う方法についての提案を持っているでしょうか?

6
foolsparadise

できるよ:

for f in *.conf; do
    base=$(basename "$f" '.conf') # gives '25' from '25.conf'
    sed -i.before "s/example/$base/g" "$f"
done

-iスイッチをsedに使用する場合、-iがファイルを変更するため、sedコマンドが機能することを完全に確認する必要がありますin-place。これは、生成された出力が入力ファイルを上書きすることを意味します。置換コマンド(s/…/…/)が間違っていると、空のファイルが作成され、バックアップが作成されない場合があります。そのため、-i.beforeを使用しました。これにより、元のコンテンツを含む*.beforeファイルが残ります。

8
PerlDuck

Forループを使用して、ファイルを反復処理できます。パラメーター拡張を使用して、ファイル拡張子を削除します。式を二重引用符で囲みます。そうしないと、変数は展開されません。

#! /bin/bash
for f in *.conf ; do
    b=${f%.conf}
    sed -i "s/example/$b/" "$f"
done
5
choroba

GNU parallelを使用して、ループなしでタスクを実行できます。Install parallel

parallel sed -i.old s/example/{.}/ {} ::: *.conf

これは、parallelがCPUコアごとに1つのジョブを実行するため、編集するファイルのlotがある場合に特に役立ちます。

  • -i.oldは、ファイルin-placeを編集し、元のファイル名に.old拡張子を追加してバックアップを作成します(バックアップが不要な場合は.oldを削除しますが、覚えていない場合は ' tバックアップがあります)
  • s/example/{.}/gは、substitute exampleを意味し、拡張子のない入力ファイル名({.})で、globally(=すべての出現に対して)
  • {}は入力ファイル名に置き換えられます
  • :::は、実行するコマンドとそれに渡す引数を分離します
  • *.confは、現在のディレクトリ内のすべての.confファイルと一致します
2
dessert

FILENAME変数がファイル名に自動的に設定されているawkを使用します(GNU awkの場合、インプレース編集も行います)。

$ for i in {20..26}; do printf "%s\n" "datafname = example.nex" "ofprefix = best.example" > $i.conf; done
$ gawk -i inplace 'FNR == 1 {split(FILENAME, file, ".")} {gsub("example", file[1])} 1' *.conf
$ cat 25.conf
datafname = 25.nex
ofprefix = best.25
  • FNR == 1 {split(FILENAME, file, ".")}:各ファイルの最初の行で、.でファイル名を分割し、file配列に保存します
  • {gsub("example", file[1])} 1:すべての行について、examplefile配列の最初の要素に置き換えて印刷します。
1
muru