sed 或 Perl 一个衬里 + 如何仅在完全匹配时替换文件中的路径

sed or Perl one liner + how to replace path in file only when full match

我们想从

替换 /etc/fstab 文件上的路径
/dev/sdb /var/kafka ext4 defaults,noatime 0 0

至(预期输出)

/dev/sdb /var/kafka/hadoop_kafka ext4 defaults,noatime 0 0

我们写的sed语法是

sed s'/\/var\/kafka/\/var\/kafka\/hadoop_kafka/g' /etc/fstab

所以一旦我们 运行 然后我们进入 fstab this

/dev/sdb /var/kafka/hadoop_kafka ext4 defaults,noatime 0 0

但是一旦我们再次 运行 sed 然后我们在 fstab 中得到错误的路径:

/dev/sdb /var/kafka/hadoop_kafka/hadoop_kafka ext4 defaults,noatime 0 0

那么如何替换路径,只有在我们匹配路径的情况下:

/var/kafka

以下'awk'可以为您提供帮助

$ awk '(=="/var/kafka"){="/var/kafka/hadoop_kafka"}1' file

awk 的操作方式很简单,另一方面,它的语法对于外行来说可能有点不寻常。 awk 对记录进行操作,默认情况下是行,每条记录都分成字段。默认情况下,这些字段由一系列一个或多个空格(空格、制表符...)分隔。对于每个记录,awk 将处理一系列以 (pattern){action} 形式编写的模式-动作对。你可以很简单地读到这个是如果pattern为真,执行action。默认模式为 true,默认操作为 print.

当我们查看上面的内容时,我们会看到以下两个模式-动作对:

  • (=="/var/kafka"){="/var/kafka/hadoop_kafka"}。这个我们可以翻译为:如果第二个字段等于“/var/kafka”,则将第二个字段替换为“/var/kafka/hadoop_kafka”
  • 1:这只是说一个,等于“真”,是一个模式,所以我们添加默认动作{print}。所以这条语句只打印当前行。

根据您显示的 samples/attempts,请尝试执行以下 sed 程序。

sed -E 's/^([^ ]*\s+)(\/var\/kafka)(\s.*)/\/hadoop_kafka/ Input_file

解释:首先使用sed-E选项启用ERE(扩展正则表达式),然后使用 s 选项在这里执行替换。在替换部分正则表达式中使用反向引用概念(将匹配值保存在临时缓冲存储器中,稍后在程序中使用)。

  • ^([^ ]*\s+):匹配从 space 第一次出现的所有内容进入第一个捕获组。
  • (\/var\/kafka):创建第二个捕获组,确保它匹配其中的 /var/kafka
  • (\s.*): 匹配此处剩余的行。

在执行替换时根据要求在第二个捕获组之后添加 \/hadoop_kafka

注意: 以上代码将在终端上打印值,一旦您对结果满意,请使用 -i 选项就地保存到 Input_file.

你可以试试这个sed:

sed -i.bak -E 's~(^|[[:blank:]])/var/kafka([[:blank:]])~/var/kafka/hadoop_kafka~g' /etc/fstab

正则表达式详细信息:

  • (^|[[:blank:]]):匹配开始或捕获组 #1 中的 space 或制表符
  • /var/kafka:匹配文本/var/kafka
  • ([[:blank:]]):匹配捕获组 #2
  • 中的 space 或制表符
  • /var/kafka/hadoop_kafka:在替换中放回第 1 组中捕获的值,然后是 /var/kafka/hadoop_kafka,然后是第 2 组中捕获的值
perl -pe's{^\S+\s+/var/kafka\K(?=\s)}{/hadoop_kafka}'

你会如何使用它:

perl -i -pe's{^\S+\s+/var/kafka\K(?=\s)}{/hadoop_kafka}' /etc/fstab

您想替换第二个字段,它位于非空白前导序列之后的空白之间。

s{
   ^ ( \S+ \s+ ) /var/kafka ( \s | $ )
}{
    . "/var/kafka/hadoop_kafka" . 
}ex

那么,你想要

perl -pe'
   s{
      ^ ( \S+ \s+ ) /var/kafka ( \s | $ )
   }{
       . "/var/kafka/hadoop_kafka" . 
   }ex
'

或同等水平

perl -pe's{^\S+\s+/var/kafka\K(?=\s)}{/hadoop_kafka}'