繁体   English   中英

使用 sed 在模式后添加文本,但添加的文本来自列表文件

[英]Using sed to add text after a pattern, but the added text comes from a list file

如何使用 sed 定位字符串,并在字符串后添加另一个文件中的文本?

文件 1:

stage ('Clone Repo31') {

        steps {
                git credentialsId: '', url: '/stash/scm/'
        }
    }
    stage ('Zip Repo31') {
        steps {
        sh"""
            tar --exclude='*.tar' -cvf .tar *
        """
        }
    }
    steps {
            git credentialsId: '', url: '/stash/scm/'
    }
}
stage ('Zip Repo32') {
    steps {
    sh"""
        tar --exclude='*.tar' -cvf .tar *
    """
    }
}

文件2:

randomRepo.git
differentRandomRepo.git

我希望能够使用 sed 读取第二个文件,并在每次出现 stash/scm/ 后添加第二个文件中每一行的内容

期望的输出:

       stage ('Clone Repo31') {

        steps {
                git credentialsId: '', url: '/stash/scm/randomRepo.git'
        }
    }
    stage ('Zip Repo31') {
        steps {
        sh"""
            tar --exclude='*.tar' -cvf .tar *
        """
        }
    }
    steps {
            git credentialsId: '', url: '/stash/scm/differentRandomRepo.git'
    }
}
stage ('Zip Repo32') {
    steps {
    sh"""
        tar --exclude='*.tar' -cvf .tar *
    """
    }
}

这可以用sed完成吗? 我在从列表文件中读取它时遇到问题,这很令人困惑,因为它有很多斜线。 我已经能够使用普通的 sed 替换,但我不知道如何通过读取另一个文件来进行替换。

下面我将介绍一个几乎纯sed解决方案。

sed有一个r命令来读取文件,所以原则上你可以使用它来读取file2 但是,没有后续命令会影响从文件中读取的行,因此我想不出任何有效地使用r命令来执行您要求的方法。

但是,如果file1file2都在sed输入中给出,则解决方案是可能的。

下面,为了区分这两个文件,我放了一个标记行( ----- ),我认为理所当然不在file2 但是,它可以位于file1中的任何位置而不会产生任何问题。

cat file2 <(echo '-----') file1 | sed -f script.sed

其中script.sed如下:

1{                     # only on line 1
  :a                   # begin while
  /-----/!{            # while the line does not contain the marker
    N                  # append the following line
    ba                 # end while
  }                    # here the pattern space is a multiline containing the list
  s/\n-----//          # remove the last newline and the marker
  h                    # put the multiline in the hold space
  d                    # delete, as we don't want to print anything so far
}                      # that's it, lines from 1 to the marker are processed
/stash\/scm\//{        # for lines matching this pattern
  G                    # we append the full hold space
  s/'\n\([^\n]*\)/\1'/ # and position the first entry in the list appropriately
  x                    # then we swap pattern and hold space
  s/[^\n]*\n//         # remove the first element of the list
  x                    # and swap again
}                      # now the hold space has one item less

这是一个bash脚本,它使用sed并逐行读取 File_2(包含替换的文件),从而一次读取一个替换。 然后我用 sed 脚本替换了 File_1 中的行。

while IFS= read -r line; do
    sed -i "0,/\/stash\/scm\/'/{s|/stash/scm/'|/stash/scm/${line}'|}" File_1.txt
done < File_2.txt

一些技巧用于做到这一点:

  1. sed '0,/Apple/{s/Apple/Banana/}' input_filename只用字符串Banana替换字符串Apple文件名中的第一次出现
  2. sed脚本使用双引号以允许变量扩展${line}
  3. 确保每次迭代都更改要替换的搜索字符串。 这是通过在 sed 脚本s|/stash/scm/'|包含搜索参数的结尾单引号字符'来完成的s|/stash/scm/'|
  4. 在bash脚本中逐行读取文件
while IFS= read -r line; do
    echo $line
done < File_2.txt

在bash中逐行读取文件

你想要像这样的线条

sed 's#'/stash/scm/'#&something_from_file2#' file1 

你可以用这些线

    # Note:
    # / is not a delimiter, but part of the path
    # % is the delimiter in the current sed-command
    # # is the delimiter in the generated command.

sed 's%.*%s#/stash/scm/#\&&#%' file2

您可以即时生成这些命令并在 file1 上执行它们。

sed -f <(sed 's%.*%s#/stash/scm/#\&&#%' file2) file1

还剩一个问题。 这两个命令都将替换所有匹配项。
我将使用比赛后给出的单引号。 当在/stash/scm/'的单引号之前放置某些内容时,这与查找包含引号的/stash/scm/'字符串时的匹配文件不同。
你想生成像

s#(/stash/scm/)(')#\1randomRepo.git\2#
s#(/stash/scm/)(')#\1differentRandomRepo.git\2#

每个替换应该只执行一次,因此我们使用选项-z将 file2 视为一个长行:

sed -rzf <(sed 's%.*%s#(/stash/scm/)('\'')#\\1&\\2#%' file2) file1 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM