【问题标题】:Merge files with AWK while adding separators before and after使用 AWK 合并文件,同时在前后添加分隔符
【发布时间】:2015-03-01 06:32:52
【问题描述】:

我正在尝试使用 AWK 执行以下操作:

  • 从文件夹中读取一系列文件。
  • 将它们全部合并到一个文件中。
  • 在执行此操作时,我想在每个文件的开头 和结尾 放置一个分隔符(实际上是一段代码,打开和关闭标记,但在此示例中,我使用了一个简单的分隔符为清楚起见)。

我想在我的输出中看到什么:

--Separator : Beginning of File--
  ((Content of file1.txt))
--Separator : End of File--
--Separator : Beginning of File--
  ((Content of file2.txt))
--Separator : End of File--
--Separator : Beginning of File--
  ((Content of file3.txt))
--Separator : End of File--

等等……

我有这个代码 sn-p,它适用于“文件开头”分隔符:

INPUT="../folder/*.txt"
OUPUT="../output.txt"

awk 'FNR==1{print "--Separator : Beginning of File--"}{print}' $INPUT > $OUTPUT

现在我正试图弄清楚下一步:检测每个文件的结尾,并在那里放置一个分隔符。

我发现了几个使用 END 进行单文件操作的示例,但它们只检测到最后一个文件的最后一行

【问题讨论】:

    标签: awk


    【解决方案1】:

    使用 GNU awk,简单

    awk 'BEGINFILE { print "--Separator : Beginning of File--" } ENDFILE { print "--Separator : End of File--" } 1' file1 file2 file3
    

    可读格式:

    BEGINFILE { print "--Separator : Beginning of File--" }
    ENDFILE   { print "--Separator : End of File--" }
    1
    

    其中前两行似乎不言自明; BEGINFILEENDFILE 是 GNU 特定的条件,分别适用于已处理文件的开头和结尾。最后一种是不改变打印行的惯用方式。 1 表示 true,因此此条件适用于所有行,并且在没有关联操作的情况下,将为它们执行默认操作 - 打印。

    符合 POSIX 标准:

    awk 'BEGIN { start = "--Separator : Beginning of File--"; end = "--Separator : End of File--"; print start } FNR == 1 && FNR != NR { print end; print start } { print } END { print end }' file1 file2 file3
    

    可读格式:

    BEGIN {
      # In the beginning, put the separators in variables so we don't have to
      # repeat ourselves
      start = "--Separator : Beginning of File--"
      end   = "--Separator : End of File--"
    
      # and print the first beginning separator
      print start
    }
    
    # For the first line of all files (FNR == 1) except that of the first
    # file (in the first file, the file record number FNR is equal to the
    # overall record number NR, so FNR != NR tests for this)
    FNR == 1 && FNR != NR { 
      # print the end separator for the previous file
      # and the start separator for this one.
      print end
      print start
    }
    
    # print all lines unchanged (no condition means it applies unconditionally)
    { print }
    
    END {
      # and in the end, print the last end separator.
      print end
    }
    

    【讨论】:

    • 对。对于 OP - 如果您有任何空输入文件,非 gawk 解决方案可能会表现得不理想,因为它只会像它们不存在一样,而不是添加开始/结束分隔符,中间没有任何内容。这是一个问题吗?
    • 太棒了!我在 Mac OSX 上运行 awk,所以第二个版本适合我。
    • @Wintermute – 我很想在您的代码示例中添加一些换行符,以便更清楚地说明它们的作用。在它们当前的形状中,线条太长而无法完整显示。我相信这些都是很好的例子,可以帮助初学者理解 awk 的工作原理。
    • 是的,不错的主意。我在它的时候放了一些cmets。
    【解决方案2】:

    如果你不绑定awk,在shell里面很简单:

    for file in ../folder/*.txt; do
        echo "--start"
        cat "$file"
        echo "--end"
    done > ../output.txt
    

    【讨论】:

    • 谢谢,这确实是一个不错的选择。我将在这些文件中做几个正则表达式替换,这就是为什么 awk 似乎是最合适的工具。
    • 同意。如果开始/结束分隔符相当“愚蠢”,您可以在 for 循环中将 cat 替换为 awk
    猜你喜欢
    • 2017-11-16
    • 2019-05-15
    • 2012-11-02
    • 1970-01-01
    • 1970-01-01
    • 2016-07-03
    • 2021-05-14
    • 2020-05-18
    • 1970-01-01
    相关资源
    最近更新 更多