【问题标题】:How to replace a match with an entire file in BASH?如何用 BASH 中的整个文件替换匹配项?
【发布时间】:2021-12-03 21:11:41
【问题描述】:

我有这样一行:

输入文件1

如何让 bash 读取该行并直接复制“file1.txt”的内容来代替该行?或者如果它看到:INPUT file2 在一行中,放入 `file2.txt" 等。

我能做的最好的就是大量的tr 命令,将文件粘贴在一起,但这似乎是一个过于复杂的解决方案。

'sed'也是用字符串替换行,但是我不知道如何输入一个文件的全部内容,可能是几百行的替换。

【问题讨论】:

  • 大多数操作系统不能用不同大小的文本替换文件内容。每个答案都归结为“将所有内容写入新的临时文件,然后用临时文件替换原始文件”。

标签: bash replace


【解决方案1】:

Sed 解决方案类似于 awk 给出的错误:

$ cat f 
test1

INPUT f1

test2

INPUT f2

test3

$ cat f1
new string 1

$ cat f2
new string 2

$ sed 's/INPUT \(.*\)/cat \1/e' f
test1

new string 1

test2

new string 2

test3

Bash 变体

while read -r line; do
    [[ $line =~ INPUT.* ]] && { tmp=($BASH_REMATCH); cat ${tmp[1]}; } || echo $line
done < f

【讨论】:

    【解决方案2】:

    如果您想在纯 Bash 中执行此操作,这里有一个示例:

    #!/usr/bin/env bash
    
    if (( $# < 1 )); then
        echo "Usage: ${0##*/} FILE..."
        exit 2
    fi
    
    for file; do
        readarray -t lines < "${file}"
        for line in "${lines[@]}"; do
            if [[ "${line}" == "INPUT "* ]]; then
                cat "${line#"INPUT "}"
                continue
            fi
            echo "${line}"
        done > "${file}"
    done
    

    保存到文件并像这样运行:./script.sh input.txt(其中input.txt 是一个包含与INPUT &lt;file&gt; 语句混合的文本的文件)。

    【讨论】:

      【解决方案3】:

      不是最有效的方法,但作为练习,我创建了一个名为 x 的文件进行编辑,并创建了几个名为 t1t2 的输入源。

      $: cat x
      a
      INPUT t2
      b
      INPUT t1
      c
      $: while read k f;do sed -ni "/$k $f/!p; /$k $f/r $f" x;done< <( grep INPUT x )
      $: cat x
      a
      
      here's
       ==> t2
      
      b
      
      this
      is
      file ==> t1
      
      c
      

      是的,空行在 INPUT 文件中。
      不过,这将重复 sed 您的基本文件。
      给出的awk 解决方案更好,因为它只读取一次。

      【讨论】:

        【解决方案4】:

        perl 单行程序,使用 CPAN 模块 Path::Tiny

        perl -MPath::Tiny -pe 's/INPUT (\w+)/path("$1.txt")->slurp/e' input_file
        

        使用perl -i -M...就地编辑文件。

        【讨论】:

          【解决方案5】:

          awk 看起来很简单。您可能希望以不同方式/更优雅地处理错误,但是:

          $ cat file1
          Line 1 of file 1
          $ cat file2
          Line 1 of file 2
          $ cat input
          This is some content
          INPUT file1
          This is more content
          INPUT file2
          This file does not exist
          INPUT file3
          $ awk '$1=="INPUT" {system("cat " $2); next}1' input
          This is some content
          Line 1 of file 1
          This is more content
          Line 1 of file 2
          This file does not exist
          cat: file3: No such file or directory
          

          【讨论】:

            猜你喜欢
            • 2018-09-21
            • 1970-01-01
            • 1970-01-01
            • 2012-08-25
            • 2010-09-13
            • 2022-01-08
            • 2021-01-05
            相关资源
            最近更新 更多