3

ディレクトリ(Linux)内のすべてのソースファイルに、著作権ヘッダーなどのいくつかのコメントを更新または挿入しようとしています。私のファイルには一貫性がないため、いくつかのファイルにはすでにヘッダーがあり、他のファイルにはまったくヘッダーがありません。sed最初の数行を見て置き換えてみました。置換私は、すでに著作権ヘッダーを持っているファイルを最新のものに変更することを意味します。

sed -e '1,10 s/Copyright/*Copyright*/g' file

ただし、パターンが見つからなかった場合、これは挿入されません。どうすればこれを達成できますか?

コメントで提供した例、または実際に置き換え/挿入しようとしているのは、次のような複数行の一般的な著作権ヘッダーです。

/*
* Copyright 1234 XXXNAME, XYZPlace 
*  text text text text ...........
* blah blah blah */

特殊文字が含まれている場合もあります。

4

3 に答える 3

9

私が正しく理解している場合、あなたは次のことを望んでいます:

  • 最初の 10 行に著作権表示がないファイルを検索し、
  • それらのファイルに著作権表示を追加します。

さらに、次のことを行います。

  • 最初の 10 行に著作権表示のあるファイルを検索し、
  • 通知を標準テキストに更新します。

これらの 2 つのタスクは、1 つのセットにまとめることができるように思えます。

  • 最初の 10 行にある既存の著作権表示を削除してから、
  • 新しい著作権表示をファイルに挿入します。

質問に対するコメントに入力したサンプルテキストの短縮バージョンが有効であり、たとえば各ファイルの 2 行目に挿入する必要があると安全に想定できる場合、次の場合、要件の最初のセットを達成する必要があります。あなたはGNU sedを使用しています:

find . -type f -not -exec grep -q Copyright {} \; -exec sed -i'' '2i/* Copyright */' {} \;

GNU sed を実行していない場合(つまり、FreeBSD、OSX、Solaris などを使用している場合)、sed スクリプトが異なるため、お知らせください。

これはどのように機能しますか?

findコマンドは次のオプションを取得しています。

  • -type fディレクトリやデバイスではなく、ファイルのみを見るように指示します。
  • -not次のオプションを反転します。
  • -exec grep -q Copyright {} \;著作権が含まれているものに検索を制限します (によって変更されました-not)
  • -exec sed -i'' '2i/* Copyright */' {} \;著作権表示を挿入します。

sed スクリプトによって解釈される特殊文字を著作権表示に含めたい場合、この解決策は困難になる可能性があります。しかし、それはあなたの質問に答えます。:)

代わりに、改訂された要件を処理したい場合、つまり既存の著作権表示を最初に削除したい場合は、2 つのワンライナーでこれを行うことができます。

まず、既存の著作権表示を削除します。

find . -type f -exec sh -c 'head {} | grep -q Copyright' \; -exec sed -ne '10,$ta;/Copyright/d;:a;p' {} \;

サブディレクトリを再帰的にトラバースしたい場合を除いて、これは少し冗長かもしれません。これfindはデフォルトで行われます。sed スクリプトは、最初の 10 行に著作権情報がないファイルに対しては何も実行しないため、すべてのファイルが 1 つのディレクトリにある場合は、代わりに次のスクリプトも機能するはずです。

for file in *;do sed -ne '10,$ta;/Copyright/d;:a;p' "$file"; done

次に、新しいものを再び追加します。

for file in *;do sed -i'' '2i/* Copyright */' "$file"; done

または、サブディレクトリを介して再帰的にこれを行いたい場合:

find . -type f -exec sed -i'' '2i/* Copyright */' {} \;

最終更新:

この後、これ以上の時間を費やすことはできません。

find . -type f \
  -exec sh -c 'head {} | grep -q Copyright' \; \
  -exec sed -ne '1h;1!H;${;g;s:/\*.*Copyright.*\*/:/* Copyright 1998-2012 */' {} \;

1 つ目-execは、ファイルの最初の 10 行で "Copyright" という単語を検索します。上記の最初に投稿した例と同じように。grep が何かを見つけた場合、この条件は true を返します。

2番目-execは置換を行います。ファイル全体を sed のホールド バッファに読み込みます。次に、ファイルの最後に到達すると、( g) ホールド バッファーが考慮され、( s) 複数行の置換が行われます。

これには何らかの調整が必要になる可能性が非常に高く、ファイルの他の場所にコメントがある場合はまったく機能しない可能性があることに注意してください。GNU sed が貪欲でないスターをサポートしているかどうかは思い出せません。あなたはそれを自分で研究することができます。

これが私のテストです:

$ printf 'one\n/* Copyright blah blah\n *\n */\ntwo\n' | sed -n '1h;1!H;${;g;s:/\*.*Copyright.*\*/:/* Copyright 1998-2012 */:g;p;}'
one
/* Copyright 1998-2012 */
two

これは既存の著作権情報を維持しませんが、少なくとも複数行の問題に対処します.

于 2012-07-19T15:53:13.377 に答える
0

編集: ファイル名にスペースが含まれている場合、以下のコマンドは機能しません。最初のコメントを参照してください。

確かにsedonly で実行できますが、最初に頭に浮かんだのは、行が存在するファイルで置換を行い、次のようなものを使用して残りのファイルにヘッダーを追加することです

for f in $(grep -lv 'Copyright' *); do sed -i '1i *Copyright*' $f; done

これは、現在のフォルダー内のすべてのファイルに対して機能します。再帰が必要な場合は、-rオプションを使用してください。grep

PS-i sedテストのためにオプションを削除し、コマンドが正しく機能することが確実な場合にのみ追加することをお勧めします。

于 2012-07-19T15:12:52.737 に答える