【问题标题】:using sed or awk to insert line between two files使用 sed 或 awk 在两个文件之间插入行
【发布时间】:2017-05-11 10:10:34
【问题描述】:

我有两个文件,文件 A 和文件 B:

文件A.txt内:

lineA
lineB
lineC
lineD
lineE

在fileB.txt里面:

object1
object2

预期结果:

lineA
lineB
object1
lineC
lineD
object2
lineE

重叠两个文件我很迷茫,这是一个小文件,所以它不必非常自动。我正在尝试做这样的事情:

cat fileA.txt | sed -n 1p >> fileB.txt | 3p?
cat fileA.txt | sed -n 2p >> fileB.txt | 6p?

请帮忙

【问题讨论】:

标签: bash sed


【解决方案1】:

你可以使用这个GNU sed,如果文件A中每两行插入一行文件B。

sed 'n;R file2' file1

输出:

$ sed 'n;R file2' file1
lineA
lineB
object1
lineC
lineD
object2
lineE

来自man sed

R 文件名

附加从文件名读取的行。该命令的每次调用都会从文件中读取一行。这是一个 GNU 扩展。

【讨论】:

  • @Inian,这是GNU sed。在我的答案中更新。
  • 什么告诉 sed 在 fileA 中选择两行,然后在 fileB 中选择一行,依此类推?
【解决方案2】:

sed 用于在单个行上进行简单替换,仅此而已。如果您使用 s、g 和 p(带 -n)以外的 sed 结构,那么您使用了错误的工具。对于任何其他文本处理问题,您应该使用 awk 来获得清晰、简单、可移植、效率和大多数其他理想的软件属性:

$ awk 'NR==FNR{a[NR]=$0;next} {print} FNR%2==0{print a[++c]}' fileB fileA
lineA
lineB
object1
lineC
lineD
object2
lineE

【讨论】:

    【解决方案3】:
    sed '0~2 R file_name_2'  file_name_1
    

    0~2 - 每两行之后

    R 文件名 - 附加从文件名读取的行。每次调用 命令从文件中读取一行。

    【讨论】:

    • 您需要添加一些对答案及其工作原理的解释。否则很可能会被删除。
    【解决方案4】:

    尝试:

    awk 'FNR==NR{A[FNR]=$0;next} {printf("%s%s\n",$0,FNR%2==0?ORS A[++i]:"")}' fileB.txt fileA.txt
    

    检查 FNR==NR 条件,当读取文件 fileB.txt 时该条件为真。它正在创建名为 A 的数组,其索引是行号,它的值是 fileB.txt 行的当前行。 next 将在读取名为 fileB.txt 的文件时跳过所有进一步的语句。 打印 fileA.txt 的当前行并检查条件,如果 FNR%2==0 然后打印数组 A 的值,变量 I 的值增加。

    lineA
    lineB
    object1
    lineC
    lineD
    object2
    lineE
    

    【讨论】:

    • 恕我直言,对于这个问题,getline 比 FNR==NR 更好,因为它不需要加载整个文件。
    • print $0 (FNR%2 ? "" : ORS A[++i]) 而不是 printf("%s%s\n",$0,FNR%2==0?ORS A[++i]:"") 恕我直言会更清楚。
    【解决方案5】:

    awk 中的另一个,使用 mod (%) 和 getline

    awk '1;NR%2==0{if((getline line < "fileB")>0)print line}' fileA
    lineA
    lineB
    object1
    lineC
    lineD
    object2
    lineE
    

    fileA 中的每一行之后,如果有任何剩余,则从fileB 打印一行。

    【讨论】:

    • 恕我直言,对于这个问题,getline 比 FNR==NR 更好,因为它不需要加载整个文件。
    • @Setop OP 特别提到了it is a small files 那么为什么要让自己接受向 getline 解决方案添加功能的复杂性、警告和困难(请参阅awk.freeshell.org/AllAboutGetline)?例如,假设您意识到您不想从任一文件中打印以 # 开头的行 - 使用 getline 解决方案,您需要在 2 个不同的位置添加该测试,因为您以不同的方式读取每个文件,但使用非getline 解决方案,您一开始只需要/^#/{next}。如果您只想在最后打印总行数(END{print NR} 不起作用)怎么办?等等……
    • @EdMorton 一般来说,/^#/{next} 是一个很好的例子,但在这个特定的问题中,如果在 lineBfileA 的前面添加了 #,则会导致 @987654335 @ of fileB 将被跳过 - 或移动到下一个位置 - 以及。
    • 在我试图给出的示例中,任一文件中以# 开头的任何行都应该被跳过。是的,FNR 也必须做一些事情,但我试图表达的观点(可能很糟糕)是,当你有 2 种完全不同的方式来读取输入文件时,很难编写处理过程中常见的代码两个输入文件。
    • @JamesBrown 是的,您使用 getline 的方式是安全的。唯一的问题是,如果/当需求发生变化并且“fileB”是硬编码时,它不容易扩展,这可能并不理想。
    猜你喜欢
    • 1970-01-01
    • 2014-09-07
    • 2017-05-25
    • 2022-08-15
    • 2011-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-01
    相关资源
    最近更新 更多