我有一个文件我在其中有一个命名约定
.
.
.
delay_rise = 20ps
delay_rise = 40ps
.
.
.
我需要将第二次delay_rise更改为delay_fall。我该怎么办?
答案 0 :(得分:1)
使用awk:
f
这可以通过设置计数器delay_rise
来查看我们看到包含f==2
的行的次数。当且仅当我们第二次出现delay_fall
时,我们才会在1
中替换。
脚本末尾的-i inplace
是awk用于打印此行的神秘符号。
如果您有最新版本的GNU awk,只需在命令行中列出所有文件并使用awk -i inplace '/delay_rise/ {f++; if (f==2) sub(/delay_rise/, "delay_fall")} 1' file*
选项:
for f in file*; do awk '/delay_rise/ {f++; if (f==2) sub(/delay_rise/, "delay_fall")} 1' "$f" >tmp.out && mv tmp.out "$f"; done
如果您有BSD awk或更旧的GNU awk,请使用:
for f in file*
do
awk '/delay_rise/ {f++; if (f==2) sub(/delay_rise/, "delay_fall")} 1' "$f" >tmp.out && mv tmp.out "$f"
done
如果您希望将命令分散在多行中,则可以将以下命令运行为:
{{1}}
答案 1 :(得分:0)
你可以通过很多方式在shell中做到这一点。
这适用于任何POSIX shell:
#!/bin/sh
flag=0
while read line; do
case "$line" in
delay_rise*)
if [ "$flag" -eq 0 ]; then
flag=1
else
line="delay_fall${line#delay_rise}"
flag=0
fi
;;
esac
echo "$line"
done
请注意,flag=0
语句中的if
允许您使用它来处理多个"对"在一个文件中。这是一个状态变化,它会切换。
另一种选择是awk。约翰的awk解决方案非常出色,但有很多方法可以完成任务。我的情况与他相似,但更为简短:
awk '/^delay_rise/&&f{sub(/rise/,"fall")} /^delay_rise/{f=1} 1' file
这可以将f
视为信号量而不是计数器。但同样,如果你需要处理每个文件的多对,重置信号量需要一些小的补充:
awk '/^delay_rise/&&f{sub(/rise/,"fall");f=0;print;next} /^delay_rise/{f=1} 1' file
拆分以便于阅读,这看起来像:
awk '
# If we find our text AND the flag is set...
/^delay_rise/ && f {
sub(/rise/,"fall"); # replace text
f=0; # reset semaphore
print; # print the line, and
next; # move on to the next line.
}
# If this is an interesting line and the semaphore was NOT set...
/^delay_rise/ {
# set it!
f=1;
}
# Print whatever we've got.
1
' file
答案 2 :(得分:0)
一个简单的方法是设置一个计数器并检查它是否为2(第二次出现)并在那里替换。一个类似的东西的Perl脚本是:
#!/usr/bin/perl
use strict;
use warnings;
my $i=0;
while(<>){
if(/delay_rise/)
{
++$i;
if($i==2)
{
s/delay_rise/delay_fall/;
}
}
print $_;
}