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 行上方的注释,您将在循环内调用 sed,使用从 Mapfile 读取的变量,如下所示:
sed "s/prj1/DCMS_DEMO/g"
对于 Mapfile 的第一行,
sed "s/blk1/de_top/g"
对于 Mapfile 的第二行,等等
这个解决方案有一个陷阱:sed 将被调用多次,从映射文件中每行读取一次,因此性能会很慢。
为了加快速度,您可以“构建”一个“替换脚本”,该脚本可以在最后为 sed 提供一次。为此,我们可以在循环内执行类似的操作:
echo "s/$old/$new/g;" >>replacements
当循环完成并且整个 sed 替换脚本准备就绪时,您可以在最后调用 sed 一次,如下所示:
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
打开的文件in-place edit
-i
。它首先从 生成一个映射哈希,mapfile.txt
然后将其应用于 Perl 参数列表中的所有后续文件。
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 {} +