mapfile.txt
私のLinuxコンピュータには、次の小さなテキストファイル()があります。別のディレクトリとサブディレクトリ内の他のファイルの名前を変更するには、このファイルの情報を使用する必要があります。どうすればいいですか?
質問のヒント:
1.i need to rename the contents of the file .
2. we should match the any of .config files in the folders and sub folders.The rename should as follows.Column 3 names in the input file should be renamed to column 2 names in the outfile.
3.Yes only the first field should be replaced.
私はこれを試しました:
s/search/replace/g
しかし、これは正しい形式ではありません。
マップファイル.txt:
PROJECT:DCMS_DEMO:prj1
BLOCK:de_top:blk1
BLOCK:new_block2:blk2
BLOCK:test:blk3
CHECKLIST:Block_DV:checklist1
その他の書類は次のとおりです。
blk3 : 0% : 0%
blk1 : 0.68% : 0.99%
blk2 : 0.00% : 0.00%
OVERALL_STATUS=0.23%
PARTIAL_STATUS=0.33%
期待される:
test : 0% : 0%
de_top : 0.68% : 0.99%
new_block2: 0.00% : 0.00%
OVERALL_STATUS=0.23%
PARTIAL_STATUS=0.33%
答え1
そしてawk
:
awk -F ":" -v OFS=":" 'FNR==NR{a[$3" "]=$2" ";next} $1 in a{ $1=a[$1] };1' mapfile.txt otherfile.txt
出力:
test : 0% : 0%
de_top : 0.68% : 0.99%
new_block2 : 0.00% : 0.00%
OVERALL_STATUS=0.23%
PARTIAL_STATUS=0.33%
答え2
次のソリューションを適用して、ファイル(または追加ファイル)の内容を置き換えることができます。
まず、次のようにマッピングファイルを繰り返すことができます。
while IFS=: read -r desc new old;do #IFS is used to set the delimiter, : in your case
echo "description=$desc - old value:$old - to be replaced with : $new"
#i usually apply this echo as a cross check that all field are read correctly
#more actions here like:
#sed -i "s/$old/$new/g" file1
done <mapfile
上記のsed行のコメントを外すと、Mapfileから読み込まれた変数を使用してループ内でsedを呼び出すことができます。たとえば、
sed "s/prj1/DCMS_DEMO/g"
Mapfileの最初の行、
sed "s/blk1/de_top/g"
Mapfileの2番目の行などです。
このソリューションにはトラップがあります。 sed が複数回呼び出され、マップファイルの各行が 1 回読み込まれるため、パフォーマンスが低下します。
作業速度を上げるには、最後にsedを一度提供する「代替スクリプト」を「構築」することができます。これを行うには、ループ内で次のことを実行できます。
echo "s/$old/$new/g;" >>replacements
ループが完了し、完全なsed置換スクリプトが準備されたら、次のように最後にsedを1回呼び出すことができます。
sed -f replacements file1
sed 置換スクリプトを使用したデモ
#!/bin/bash
clear
echo "Original File1"
cat file1
while IFS=: read -r desc new old;do
echo "s/$old/$new/g;" >>replacements
done <mapfile
echo && echo "Replacements for sed"
cat replacements
echo && echo "file1 replaced"
sed -f replacements file1
rm replacements
#Output:
Original File1
blk3 : 0% : 0%
blk1 : 0.68% : 0.99%
blk2 : 0.00% : 0.00%
OVERALL_STATUS=0.23%
PARTIAL_STATUS=0.33%
Replacements for sed
s/prj1/DCMS_DEMO/g;
s/blk1/de_top/g;
s/blk2/new_block2/g;
s/blk3/test/g;
s/checklist1/Block_DV/g;
file1 replaced
test : 0% : 0%
de_top : 0.68% : 0.99%
new_block2 : 0.00% : 0.00%
OVERALL_STATUS=0.23%
PARTIAL_STATUS=0.33%
ヒント:
file1の使用法を永久に変更する必要がある場合は、sed -i
同じsedスクリプトをディレクトリ内のより多くのファイルに適用する必要がある場合は、次のようにします。
sed -i -f replacements * #or /dir/* or *.txt etc
答え3
find . -type f -name '*.config' -exec \
perl -wMstrict -Mvars='*h' -F':' -i -pale '
BEGIN {
local(@ARGV, $/) = shift;
chop(local $_ = <>); print;
%h = reverse /^[^:]+:\K(.+?):(.*)$/gm;
}
s//$h{$&}/ if exists $h{ (/\S+/g)[0] };
' mapfile.txt {} +
出力
test : 0% : 0%
de_top : 0.68% : 0.99%
new_block2 : 0.00% : 0.00%
OVERALL_STATUS=0.23%
PARTIAL_STATUS=0.33%
単に
find
現在のディレクトリから始まるすべてのファイルを見つけ、拡張子を持つファイルを見て、モードで開かれたファイルを.config
提供します。まず、マップからハッシュを生成し、Perl引数リストのすべての後続のファイルに適用します。Perl
in-place edit
-i
mapfile.txt
find . -type f -name '*.config' -exec \
perl -F: -i -ple '$. == ++$h and $h{$F[2]} = $F[1], 1 or exists $h{(/\S+/g)[0]} and s//$h{$&}/;
$h = 0 if eof' mapfile.txt {} +