查找,替换或插入 - 命令行

时间:2015-07-02 08:17:05

标签: linux replace sed insert find

我的列表类似于:

What do you want to do?
Import a text file by opening it in Excel
Import a text file by connecting to it
Export data to a text file by saving it
Change the delimiter that is used in a text file
Change the separator in all .csv text files

使用SED我可以在'连接'上找到匹配并替换该行:

 sed 's^.*connecting.*^Import a text file by opening it^g' crontab

这应该将上面的列表更改为:

What do you want to do?
Import a text file by opening it in Excel
Import a text file by opening it
Export data to a text file by saving it
Change the delimiter that is used in a text file
Change the separator in all .csv text files

然而,我需要做的是:

如果存在包含单词connecting的行,则替换该行, 如果该行不存在,请将其作为新行添加到列表的末尾。

我知道我可以echo "Import a text file by opening it" >> list将行添加到列表末尾,但无论如何我可以在一个命令中执行此操作吗?或者可以在一个实例中运行的命令?

由于

2 个答案:

答案 0 :(得分:2)

一种简单的方法是使用awk

awk 'BEGIN { s = "Import a text file by opening it" } /connecting/ { $0 = s; n = 1 } 1; END { if(!n) print s }' filename

其工作原理如下:

BEGIN {                                    # Before anything else:
  s = "Import a text file by opening it"   # Remember the string by a shorter
                                           # name so we don't have to repeat it
}
/connecting/ {                             # If a line contains "connecting",
  $0 = s                                   # replace the line with that string
  n = 1                                    # and raise a flag that we've done so.
}
1                                          # print
END {                                      # in the end:
  if(!n) {                                 # If the string wasn't yet printed,
    print s                                # do it now.
  }
}

或者,您可以使用sed的保留缓冲区。例如:

sed '1 { x; s/.*/Import a text file by opening it/; x; }; /connecting/ { s/.*//; x; }; $ { G; s/\n$//; }' filename

其工作原理如下:

1 {                                        # while processing the first line
  x                                        # swap hold buffer, pattern space
  s/.*/Import a text file by opening it/   # write text to pattern space
  x                                        # swap back.
}                                          # Now the hold buffer contains the
                                           # line we want to insert, and the
                                           # pattern space the first line.

/connecting/ {                             # For all lines: If a line contains
                                           # "connecting"
  s/.*//                                   # empty the pattern space
  x                                        # swap in hold buffer.
                                           # If this happened, the hold buffer
                                           # will be empty and the pattern space
                                           # will contain "Import a ..."
}
$ {                                        # Last line:
  G                                        # Append hold buffer to pattern space.
                                           # If the hold buffer is empty (i.e.,
                                           # was used somewhere else), this
                                           # appends a newline, so
  s/\n$//                                  # remove it if that happened.
}

请注意,sed代码取决于只有一行包含"连接。"如果有更多这样的行,它们将被替换为空行,因为当第二行出现时,保持缓冲区为空。有可能处理这种情况,但你必须决定它应该发生什么。由于您在评论中回复说只有一条这样的行,我觉得不需要猜测。

答案 1 :(得分:0)

您可以尝试,使用与类似的正则语法,但对于这些问题要强大得多。它只是在至少完成一次替换时设置了一个标志。解析整个文件后,在END {}块中,如果尚未设置$flag变量,请添加注释:

perl -pe '
    s/^.*connecting.*$/Import a text file by opening it/ and $done = 1;
    END { printf qq|%s\n|, q|Import a text file by opening it| unless $done }
' infile

找到该行后,它会产生:

What do you want to do?
Import a text file by opening it in Excel
Import a text file by opening it
Export data to a text file by saving it
Change the delimiter that is used in a text file
Change the separator in all .csv text files

如果找不到,则产生:

What do you want to do?
Import a text file by opening it in Excel
Export data to a text file by saving it
Change the delimiter that is used in a text file
Change the separator in all .csv text files
Import a text file by opening it

如果它出现不止一次,请更改两者,但它不会附加任何内容:

What do you want to do?
Import a text file by opening it in Excel
Import a text file by opening it
Export data to a text file by saving it
Change the delimiter that is used in a text file
Import a text file by opening it
Change the separator in all .csv text files