【问题标题】:Insert line from file 2 into file 1 after certain letter/symbol在某些字母/符号之后将文件 2 中的行插入文件 1
【发布时间】:2018-08-20 03:04:06
【问题描述】:

我正在尝试使用 awk/sed/forloop/foreach... 以最简单的方式合并某些位置的两个文件。

首先,我有文件 1,它有 ...

#   
#   
>  
#    
#     
>

等等。

在我的第二个文件中,我只有数字(与另一个文件中的 > 一样多)。

Num1  
Num2   
Num3

等等……

我想在文件2中按顺序插入数字,在第一个文件的每个>之后,比如...

#   
#   
> Num1  
#    
#     
> Num2

谢谢!

【问题讨论】:

  • using awk/sed ,因此请尝试使用这些工具并将其添加到问题中。请参阅how much research effort is expected of SO users...如果您是初学者,请查看awk 和@ 的信息页面987654323@开始...
  • 我之前尝试了一些东西,但无法弄清楚。下次我会添加我尝试过的内容!这是我第一次在这里发帖,因为我在搜索时找不到类似的答案。感谢您的建议!
  • 给新人的建议:如果一个答案解决了您的问题,请点击旁边的大复选标记 (✓) 接受它,也可以选择投票(投票至少需要 15 声望)点)。如果您发现其他答案有帮助,请给他们投票。接受和投票有助于未来的读者。请看【相关帮助中心文章】[1] [1]:stackoverflow.com/help/someone-answers

标签: linux bash awk sed csh


【解决方案1】:

让我们考虑一下file1file2,我们需要与您的标准合并:

$ more file1 file2
::::::::::::::
file1
::::::::::::::
#
#
>
#
#
>
#
#
>
::::::::::::::
file2
::::::::::::::
98
58
348

那么你可以使用下面的awk命令:

$ awk '/^#/{print $0; next}/^>/{printf "> "; getline < "file2" ; print $0}' file1

输出:

#
#
> 98
#
#
> 58
#
#
> 348

说明:

  • /^#/{print $0; next} 对于以 # 开头的行,只需打印它并转到下一行
  • /^&gt;/{printf "&gt;"; getline &lt; "file2" ; print $0} 当一行以&gt; 开头时,您打印&gt; 后跟getline 语句从file2 提取的数字。

最后但同样重要的是,只需将命令的输出重定向到一个文件,以便通过重定向运算符 &gt; 保存结果:

$ awk '/^#/{print $0; next}/^>/{printf "> "; getline < "file2" ; print $0}' file1 > result

按照 Sundeep 的建议,您甚至可以使用更紧凑的命令:

awk '/^>/ && (getline num < "file2")==1{$0 = $0 OFS num} 1'

对于以&gt; 开头的行,您调用getline 语句从file2 获取下一行并将内容存储到num 变量中(getline 将返回1 如果成功) ,然后这将触发范围器{$0 = $0 OFS num},您在其中替换行内容本身,然后是output field separator(默认为空格),您将存储在num变量中的值连接到该范围。最后但同样重要的是,awk 命令末尾的1 用于触发$0 中包含的整个修改行的默认打印。

【讨论】:

  • 没有问题,不知道为什么你使用sed 而你有awk.. 就个人而言,我只会使用getline
  • @Sundeep:其实你是对的,即使sed 解决方案有效,它也太复杂了,getline &lt; $FILE 更直接!我已经编辑了我的答案谢谢
  • getline has many caveats though... awk '/^&gt;/ &amp;&amp; (getline num &lt; "file2")&gt;0{$0 = $0 OFS num} 1'
  • @Sundeep:我也在帖子中添加了您的解决方案! ;-) 非常紧凑我喜欢它,我已将&gt;0 更改为==1
【解决方案2】:

awk解决方案:

awk '/^>/{ r=$0; if ((getline < "file2") > 0) $0=r OFS $0 }1' file1

样本输出:

#
#
> Num1
#
#
> Num2

【讨论】:

  • 非常紧凑,与 Sundeep 解决方案非常相似(添加到我的答案中)+1!
【解决方案3】:
sed -r "/^>/R file2" file1 | sed -r "/>/d;s/^([^#])(.*)/> \1\2/"

sed 命令R file2 总是在触发时从file2 中读取一行。但它会产生一些中间输出,需要调整(由管道后面的 sed 完成) - 这是之前的中间结果:

#   
#   
>  
Num1
#    
#     
>
Num2

第二次sed调用只是standand sed vodoo:

sed -r "/>/d;s/^([^#])(.*)/> \1\2/"

删除只是“>”的行并替换这些行,而不是以#开头,前面带有“>”。 (\1=N, \2=umX)

#   
#   
> Num1
#    
#     
> Num2

这是另一种方式,几乎相同:

sed -r "/^>/R file2" file1 | sed -r "/>/d;/^[^#]/s/(.*)/> \1/"

第二个 sed 命令,第 2 部分仅匹配不以 # 开头(并且仅由 # 组成)的行,将它们替换为前面的“>”。

第三种方法是,将文件 2 替换为已在每行前面包含“>”的修改版本。

【讨论】:

    【解决方案4】:

    不需要getline:

    awk 'NR==FNR{a[NR]=$0; next} {print $0 (/>/ ? " " a[++c] :"")}' file2 file1
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-15
      • 1970-01-01
      • 1970-01-01
      • 2021-05-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多