web-dev-qa-db-ja.com

ファイルの内容を見つけて置き換えます

次のようないくつかの「include」ステートメントで始まるファイルがあります。

include foo.xyz
include bar.xyz
do c
do d

ファイルfoo.xyzdo aが含まれ、ファイルbar.xyzdo bが含まれているとします。各include file.xyzステートメントをfile.xyzのコンテキストに置き換えるスクリプトを作成するにはどうすればよいですか?次の出力になりたいです。

do a
do b
do c
do d

" sedを使用して文字列をファイルの内容に置き換えます "で解決策を試しましたが、ファイル名がハードコーディングされています。 include引数に応じて、ファイル名を動的に生成したいと思います。

4
John Wickerson

これはawkを使用した単純な再帰バージョンです。 PATHにスクリプトを作成する必要があります

#!/bin/bash
awk '
$1=="include" && NF>=2 {
   system("'$0' " $2)
   next
}
{print}' "$@"

ファイル名に特別な文字(スペースを含む)が含まれていないことを前提としています。 awkは最初のWordでインクルードをチェックし、スクリプトを呼び出して2番目のWordとして指定されたファイルを処理します。他の行が印刷されます。ここでの$0outside awkの一重引用符であり、シェル$0、つまりスクリプト名も同様であることに注意してください。

4
meuh
grep -n '^include ' yourfile |
sed  -e 's/:[^ ]* /{ r /'    \
     -e 'G;s/.$/&b&}/'       |
sed -nf - -ep       yourfile

それはうまくいくはずです。 grepはそれらを見つけますinclude行番号、最初のsedはその出力を行番号固有の[num]{r fname\nb\n}コマンドに変更し、2番目のsedprintsは、最初のスクリプトの1つではないすべての行です。

{   for   x in  a b
    do    echo "do $x">"file$x.xyz"
          echo "include file$x.xyz"
    done; printf "do %s\n"  c d
}   >yourfile
cat  yourfile

include filea.xyz
include fileb.xyz
do c
do d

これはサンプルを生成し、yourfileを表示します。

そしてこれは機能します:

grep -n '^include ' yourfile |
sed  -e 's/:[^ ]* /{ r /'    \
     -e 'G;s/.$/&b&}/'       |
sed -nf - -ep       yourfile

do a
do b
do c
do d

もちろん、readファイルは任意のサイズにすることができ、1行に制限されません。ただし、ファイル名自体は1行に制限されていますが、それ以外は多かれ少なかれ制限されていませんsedによって異なります-古いsedsには任意の名前の長さの制限がありましたが、今日最も使用されているものはありません)

2
mikeserv
cat  $(grep '^include' file.txt | cut -d" " -f2); grep -v '^include' file.txt

最初のコマンドは、file.txtgrepで始まる行、includeファイル名の部分、次にcutそれをcatします。

次のコマンドは、file.txtincludeで始まる行を除くすべての行を出力します

0
7171u