如何使用shell

时间:2015-08-29 03:21:01

标签: perl shell

我有一个文件我在其中有一个命名约定

         .
         .
         .
delay_rise = 20ps
delay_rise = 40ps
         .
         .
         .

我需要将第二次delay_rise更改为delay_fall。我该怎么办?

3 个答案:

答案 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 $_;
}