这是我的file1
:
#$BQ #{ 音量@home } #数据库达巴 #关系 tcdeatid #复制1 #{ 版本 0 } #opendb #清除 #.lruno := 72 #.infno := 1 #.tid.noel := 101 #.tid.info := 64 #.tid.setnr := 1225 <---(1225号码将更改) #.typeidm := 1 #.源表:= 2 #writedb #清除 #.lruno := 72 #.infno := 205 #.tid.noel := 101 #.tid.info := 76 #.tid.setnr := 5625 <---(5625号码将被更改) #.typeidm := 1 #.源表:= 2 #writedb #$EOJ
在 中file2
,我有正确的条目:
#.tid.info := 3345 <---(我想把这个数字放入文件1代替 64) #.tid.setnr := 1254 <---(我想把这个数字放入文件1代替 1225) #.tid.info := 5567 <---(我想把这个数字放入文件1代替 76) #.tid.setnr := 9056 <---(我想把这个数字放入文件1代替5625)
我想file1
根据来自 的数据进行更改file2
。
我努力了
sed "s/tid.setnr := 1225/tid.setnr := 1254/g" file1 > modified_file1
但我不想手动执行此操作,而是希望我的脚本读取新值tid.info
和tid.setnr
值file2
并修改file1
. in 中的第一行应替换 containsfile2
中的整个第一行,第二行应替换contains中的第二行,依此类推。file1
tid.info
file2
file1
tid.setnr
答案1
使用 GNU sed 的 R 命令:
sed -e 's/^#.tid.setnr :=.*//;tA;b;:A;R file2' -e 'd' file1
答案2
执行此操作的一种方法sed
是生成sed
脚本:
tmpfile=/tmp/Nainita.$$
exec 3< file2
grep -n "tid\.setnr" file1 | while IFS=: read n junk
do
IFS= read -r line <&3 || break
printf "%sc%s\n%s\n" "$n" '\' "$line"
done > "$tmpfile"
exec 3<&-
sed -f "$tmpfile" file1 > modified_file1
rm -f "$tmpfile"
exec 3< file2
打开file2
以读取文件描述符 3。- 按行号查找包含 ,的行
grep -n
。这被输送到一个循环中。file1
tid.setnr
while
while IFS=: read n junk
while … read …
表示一次读取一行,重复读取,只要有信息可读取(即到达数据末尾时停止)。IFS=: read n junk
:
意味着将第一行(即来自 的行号grep -n
)之前的所有内容读入n
,并将该行的其余部分(旧tid.setnr
数据行)读入junk
,我们忽略它,因为我们不关心它。
IFS= read -r line <&3
从文件描述符 3 ( ) 中读取一行file2
,执行我们知道如何执行的所有操作来告诉 shell 不要破坏它,并将其放入名为 的变量中line
。… || break
说,如果上述read
失败(可能是由于文件结尾),则跳出循环。- 写
printf
了一个sed
Change 命令,指向行号n
,表示该行应该替换为line
变量的内容。 done > "$tmpfile"
标记循环结束while
,并指定整个循环的标准输出为$tmpfile
。这最终会看起来像这样:13c\ #.tid.setnr := 1254 22c\ #.tid.setnr := 9056
- 请注意,
while
一旦从任一输入获得 EOF,循环就会终止。因此,如果行数file1
多于,则多余的行将保持不变(即,不会生成它们的命令)。同样,如果行数多于,则多余的行将被忽略。不幸的是,这种差异不会被报告,尽管添加该功能并不困难。tid.setnr
file2
c
file2
tid.setnr
file1
- 请注意,
exec 3<&-
关闭文件描述符 3。sed -f "$tmpfile" file1 > modified_file1
运行sed
在 上file1
,从 读取命令$tmpfile
并将输出写入到modified_file1
。
这应该做你想做的。显然,如果需要,可以更改文件名。您应该“按原样”运行一次,然后查看该modified_file1
文件(或者简单地更改命令sed
以不重定向其输出,以便它写入屏幕)并验证输出是否是您想要的。然后您可以将sed
命令更改为就地sed -i
编辑file1
(如果您想要这样做)。
如果该sed
命令给出诸如“行号过多”之类的错误,请尝试将脚本文件 ( $tmpfile
) 拆分为较小的文件。我建议从 100 个命令以下的大小开始;例如,90 个命令,即 180 行,因为每个命令是两行。您可以使用文本编辑器1手动执行此操作,但有一个专门为此工作编写的工具。直观上,它被称为split
.命令
split --lines=180 "$tmpfile"
会将脚本分割成当前目录中名为xaa
, xab
, xac
, ... 的文件。首先n−1 的长度为 180 行;最后一项将是构成总数所需的任何内容 (≤ 180)。例如,如果您有 500 个 实例tid.setnr
,那么您的脚本将有 1000 行长,您将得到 6 个x
文件 —
xaa
、xab
、xac
、xad
,xae
每个文件有 180 行,并且xaf
将有 100 行。现在做
sed -f xaa file1 > modified_file1aa
如果仍然出现“行数过多”,请返回并使用较少的行数重试--lines
。如果没有报错,看看modified_file1aa
前90行是不是tid.setnr
被改了。如果看起来不错,那么就做
sed -f xab modified_file1aa > modified_file1ab
sed -f xac modified_file1ab > modified_file1ac
sed -f xad modified_file1ac > modified_file1ad
sed -f xae modified_file1ad > modified_file1ae
sed -f xaf modified_file1ae > modified_file1af
modified_file1af
现在是你的最后了modified_file1
。
如果你想玩实验的话,可以
- 尝试更大的数字,
--lines
直到找出最大值是多少。 尝试
sed -f xaa -f xab -f xac -f xad -f xae -f xaf file1 > modified_file1_test
但这可能行不通。
- 如果您做了上述实验,我鼓励您告诉我们结果。
如果您只需要执行此操作一次,那么您就完成了。但是,如果您需要重复执行此操作,请将本答案顶部代码块的最后两行更改为
分割 --lines=180 "$tmpfile" <---(当然,使用适合您的数字) cp file1 修改后的文件1 对于 x* 中的 f 做 sed -i -f“$f”modified_file1 完毕 rm -f "$tmpfile" x*
正如我之前提到的,该-i
选项告诉sed
您就地编辑指定的文件(即,将更改写回输入文件)。或者,更简单的是,
split --lines=180 "$tmpfile"
for f in x*
do
sed -i -f "$f" file1
done
rm -f "$tmpfile" x*
如果您不需要保持原件file1
完好无损。
请注意,其用法概要split
是
分裂 [选项]……[输入[字首]]
它的默认行为是创建名为PREFIXaa
、PREFIXab
、PREFIXac
等的文件。换句话说,默认PREFIX
是x
。如果您可能有其他名称以 开头的文件x
,您应该定义prefix
为唯一的文件(例如,prefix=Nainita.$$.
或prefix=/tmp/Nainita.$$.
),然后将上面的内容更改为
split --lines=180 "$tmpfile" "$prefix"
for f in "$prefix"*
do
sed -i -f "$f" file1
done
rm -f "$tmpfile" "$prefix"*
______
1如果你热衷于惩罚,那么你可以这样做sed
——但为什么要玩火呢?
答案3
{ sed '/^#\.tid\.setnr/!d;=;g;G' |
paste -d'c\\\n' - - - ./addfile
} <./mainfile | sed -f - ./mainfile
它只是在前面加上相关的行号./主文件到每一行。/添加文件由命令字符串c\
和 a分隔<换行>在将结果sed
作为脚本传递给另一个进行编辑之前./主文件。根据您的示例数据,生成的脚本如下所示:
13c\
#.tid.setnr := 1254 <--- (I want to put this number in file1 in place of 1225)
22c\
#.tid.setnr := 9056 <--- (I want to put this number in file1 in place of 5625)
...指示sed
悬挂c
线13和22其输出以匹配每个命令的附加行。
答案4
我发现了perl。这个脚本是一个粗略的脚本,似乎可以解决这个问题:
#!/usr/bin/perl
#
use strict;
# subroutine to load a test file into an array
sub load{
my $file = shift;
open my $in, "<", $file or die "unable to open $file : $!";
my @data = <$in>;
chomp @data;
foreach (@data) { s/\cM//g;}
return @data;
}
my $file1 = shift || die "usage: $0 [file1] [file2]\n";
my @file1_data = &load($file1);
my $file2 = shift || die "usage: $0 [file1] [file2]\n";
my @file2_data = &load($file2);
my $i = 0;
foreach( @file1_data )
{
if( $i < @file2_data )
{
my @s = split / /, $file2_data[$i];
if( @s )
{
if( /^$s[0]/ )
{
$_ = $file2_data[$i++];
}
}
}
print "$_\n";