【问题标题】:remove above/below line and append to a file删除上/下行并附加到文件
【发布时间】:2021-04-08 05:07:08
【问题描述】:

我有一个包含以下几行的文件。我可以过滤一个特定的单词并显示它下面/上面的行。但是,我也想将其从原始文件中删除并将其附加到新文件中。

<tr>
<td>tree</td><td>apple</td><td>red</td>
</tr>
<tr>
<td>tree</td><td>apple</td><td>green</td>
</tr>
<tr>
<td>tree</td><td>apple</td><td>red</td>
</tr>
<tr>
<td>tree</td><td>apple</td><td>red</td>
</tr>

我可以通过:grep -i green origfile -A1 -B1 &gt;&gt; newfile 做到这一点,但如何从 orig 文件中删除它。

原始文件:

    <tr>
    <td>tree</td><td>apple</td><td>red</td>
    </tr>
    <tr>
    <td>tree</td><td>apple</td><td>red</td>
    </tr>
    <tr>
    <td>tree</td><td>apple</td><td>red</td>
    </tr>

新文件:

<tr>
<td>tree</td><td>apple</td><td>green</td>
</tr>

有没有更清洁/最快的方法?

【问题讨论】:

  • 与您的问题无关,但您可以使用-C2 而不是-A1 -B1。只是想我会分享
  • @kevinnls -C1,不是吗?
  • 哎呀。是的-C1。谢谢@BenjaminW。

标签: awk grep


【解决方案1】:

您可以在单个 awk 中完成此操作,将记录分隔到不同的文件中。这将查找单词green,并在其前后放置一行并将其输出到新文件中,同时将其从原始文件中删除。

awk '
FNR==NR{
  if($0~/green/){
    words[FNR]
  }
  next
}
((FNR+1) in words) || (FNR in words) || ((FNR-1) in words){
  print > "newfile"
  next
}
1
' Input_file Input_file > temp && mv temp Input_file 

说明:为上述代码添加详细说明。

awk '                       ##Starting awk program from here.
FNR==NR{                    ##Checking condition FNR==NR which will be TRUE when first time Input_file is being read.
  if($0~/green/){           ##Checking condition if line contains green string then do following.
    words[FNR]              ##Creating array of words with index of current line number.
  }
  next                      ##next will skip all further statements from here.
}
((FNR+1) in words) || (FNR in words) || ((FNR-1) in words){
##Checking condition if current line+1 OR current line OR current line-1 numbers are in words array then do following.
  print > "newfile"         ##Printing current line into newfile output file.
  next                      ##next will skip all further statements from here.
}
1                           ##Printing current line here.
' Input_file Input_file > temp && mv temp Input_file 
                            ##Mentioning Input_file(s) and doing inplace save into it.

【讨论】:

  • [not OP]:您能否详细说明这是如何工作的? (只是想学)
  • @kevinnls,是的,我正在写详细的解释,请给我几分钟:)
  • @kevinnls,现在我的回答中添加了详细的解释,干杯。
  • 就像一个魅力。谢谢@RavinderSingh13 :)
  • @gafm,欢迎您,祝您学习愉快:)
【解决方案2】:
$ cat tst.awk
$0 == "<tr>" { inRow=1; row=$0; next }
inRow {
    row = row ORS $0
    if ( $0 == "</tr>" ) {
        inRow = 0
        if ( index(row,"<td>green</td>") ) {
            print row | "cat>&2"
            next
        }
        else {
            $0 = row
        }
    }
}
!inRow

$ awk -f tst.awk file >o1 2>o2

$ head o?
==> o1 <==
<tr>
<td>tree</td><td>apple</td><td>red</td>
</tr>
<tr>
<td>tree</td><td>apple</td><td>red</td>
</tr>
<tr>
<td>tree</td><td>apple</td><td>red</td>
</tr>

==> o2 <==
<tr>
<td>tree</td><td>apple</td><td>green</td>
</tr>

修改原始文件:

$ awk -f tst.awk file >o1 2>o2 && mv o1 file

$ cat file
<tr>
<td>tree</td><td>apple</td><td>red</td>
</tr>
<tr>
<td>tree</td><td>apple</td><td>red</td>
</tr>
<tr>
<td>tree</td><td>apple</td><td>red</td>
</tr>

【讨论】:

    【解决方案3】:

    这是ed 解决方案。

    #!/usr/bin/env bash
    
    ed -s origfile.txt <<-EOF
      /<td>green<\/td>/;?^<tr>?;/^<\/tr>/w newfile.txt
      .;/^<\/tr>/d
      w
      q
    EOF
    

    或单独的ed 脚本,只需命名为script.ed

    /<td>green<\/td>/;?^<tr>?;/^<\/tr>/w newfile.txt
    .;/^<\/tr>/d
    w
    q
    

    然后

    ed -s origfile.txt < script.ed
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-11-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-04
      • 2017-03-31
      • 2021-07-05
      • 2013-03-16
      相关资源
      最近更新 更多