【问题标题】:Bash script to move specific line or lines in a file to other line with awk or sed?Bash脚本使用awk或sed将文件中的特定行或行移动到其他行?
【发布时间】:2020-12-28 01:19:23
【问题描述】:

我看到这里得到了回答: Moving matching lines in a text file using sed 和这里: How to move specified line in file to other place with regexp match (bash script)?

但我在为我的案例实施它时遇到了问题。

我有一个 .csv 文件,其中包含:

Unit Tests
Model: A
Tue Sep  8 22:52:24 MDT 2020
User: br
Files Used:
    DATA FILE - /path/to/file/data.txt
    TEST TARBALL - /path/to/tarball/my_test.tar.bz2

Results:

Module,Test Suite,Total Tests,Tests Passed,Tests Failed,Pass Rate

Individual Test Run,ClientTests,15,15,0,100.00%
,GraphTests,37,26,11,70.00%

Mean Pass Rate for All Tests,,52,41,11,78.85%

我需要移动:

Mean Pass Rate for All Tests,,52,41,11,78.85%

直到“结果”下方。所以它看起来像这样:

Unit Tests
Model: A
Tue Sep  8 22:52:24 MDT 2020
User: br
Files Used:
    DATA FILE - /path/to/file/data.txt
    TEST TARBALL - /path/to/tarball/my_test.tar.bz2

Results:
Mean Pass Rate for All Tests,,52,41,11,78.85%

Module,Test Suite,Total Tests,Tests Passed,Tests Failed,Pass Rate

Individual Test Run,ClientTests,15,15,0,100.00%
,GraphTests,37,26,11,70.00%

不保证行号。 “使用的文件”部分可能包含更多文件。此外,根据正在运行的测试,可能还有其他“平均通过率”行。例如:

Unit Tests
Model: A
Tue Sep  8 22:52:24 MDT 2020
User: br
Files Used:
    DATA FILE - /path/to/file/data.txt
    TEST TARBALL - /path/to/tarball/my_test.tar.bz2
    CLIENT FILE - /path/to/other/file/client.txt

Results:

Module,Test Suite,Total Tests,Tests Passed,Tests Failed,Pass Rate

Individual Test Run,ClientTests,15,15,0,100.00%
,ClientVarTests,12,12,0,100.00%
,GraphTests,37,26,11,70.00%

Mean Pass Rate for Client Tests,,27,27,0,100.00%
Mean Pass Rate for All Tests,,64,53,11,82.81%

在我的脚本中我尝试了 awk:

MEAN_PASS_ALL="Mean Pass Rate for All Tests"

awk '/${MEAN_PASS_ALL}/{t=$0;next}1;/RESULTS/{print t}' ${CSV_FILE}

然而,所做的只是打印出 .csv 文件的内容并且没有移动该行:

$ ./parse_results.sh
Unit Tests
Model: A
Tue Sep  8 22:52:24 MDT 2020
User: br
Files Used:
    DATA FILE - /path/to/file/data.txt
    TEST TARBALL - /path/to/tarball/my_test.tar.bz2

Results:

Module,Test Suite,Total Tests,Tests Passed,Tests Failed,Pass Rate

Individual Test Run,ClientTests,15,15,0,100.00%
,GraphTests,37,26,11,70.00%

Mean Pass Rate for All Tests,,52,41,11,78.85%

我也尝试了 sed,但出现了错误:

sed "/.*Mean/d;/.*RESULTS/i"$(sed -n '/.*Mean/p' ${CSV_FILE})  ${CSV_FILE}
$ ./parse_results.sh
sed: can't read Pass: No such file or directory
sed: can't read Rate: No such file or directory
sed: can't read for: No such file or directory
sed: can't read All: No such file or directory
sed: can't read Tests,,52,41,11,78.85%: No such file or directory
Unit Tests
Model: A
Tue Sep  8 22:52:24 MDT 2020
User: br
Files Used:
    DATA FILE - /path/to/file/data.txt
    TEST TARBALL - /path/to/tarball/my_test.tar.bz2

Results:

Module,Test Suite,Total Tests,Tests Passed,Tests Failed,Pass Rate

Individual Test Run,ClientTests,15,15,0,100.00%
,GraphTests,37,26,11,70.00%

看起来它删除了该行,但它没有将它打印到我想要​​的位置,也没有“保存”更改。

如果有多行包含“平均通过率”,我希望它们都移到“结果:”的正下方

我在这里做错了什么?如何移动文件中的行并将文件与更改一起保存?

谢谢!

【问题讨论】:

  • 如果有多个Mean Pass Rate 行,那么您是否希望它们都移到Results: 行下方?
  • @anubhava - 是的。我需要把它们都搬上来。
  • perl -0777pe 's/(Results:\n)((?:.*\n)+?)((?:Mean Pass Rate.*\n)+)/\1\3\2/'

标签: bash shell awk sed


【解决方案1】:

你可以使用 2 pass:

awk 'FNR == NR {
   if ($0 ~ /^Mean Pass Rate /)
      mpr = mpr ORS $0
      next
}
/^Results:/ {
   $0 = $0 mpr
}
!/^Mean Pass Rate /' file file
Unit Tests
Model: A
Tue Sep  8 22:52:24 MDT 2020
User: br
Files Used:
    DATA FILE - /path/to/file/data.txt
    TEST TARBALL - /path/to/tarball/my_test.tar.bz2
    CLIENT FILE - /path/to/other/file/client.txt

Results:
Mean Pass Rate for Client Tests,,27,27,0,100.00%
Mean Pass Rate for All Tests,,64,53,11,82.81%

Module,Test Suite,Total Tests,Tests Passed,Tests Failed,Pass Rate

Individual Test Run,ClientTests,15,15,0,100.00%
,ClientVarTests,12,12,0,100.00%
,GraphTests,37,26,11,70.00%

【讨论】:

  • 这真的会修改文件吗?当我运行它时,它会将输出打印到我的屏幕上,但是当我 cat 文件时,内容保持不变。
  • 不修改输入文件。您可以使用 awk -i inplace '...' file 将更改保存回 gnu-awk。
【解决方案2】:

您能否尝试在 GNU awk 中进行跟踪、编写和测试。如果您想对 Input_file 执行就地编辑,请将 > temp && mv temp Input_file 附加到以下解决方案。

awk '
FNR==NR{
  if($0~/Mean Pass Rate/){
    val=(val?val ORS:"")$0
  }
  next
}
/Results:/{
  print $0 ORS val
  val=""
  next
}
/Mean Pass Rate/{
  next
}
1
' Input_file  Input_file

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

awk '                              ##Starting awk program from here.
FNR==NR{                           ##Checking condition FNR==NR which will be TRUE when 1st Input_file is being read.
  if($0~/Mean Pass Rate/){         ##Checking condition if line has Mean Pass Rate then do following.
    val=(val?val ORS:"")$0         ##Creating val variable which is keep on having current line in it.
  }
  next                             ##next will skip all further statements from here.
}
/Results:/{                        ##Checking condition if line has Results: then do following.
  print $0 ORS val                 ##Printing current line ORS and val here.
  val=""                           ##Nullifying val here.
  next                             ##next will skip all further statements from here.
}
/Mean Pass Rate/{                  ##Checking condition if line has Mean Pass Rate then do following.
  next                             ##next will skip all further statements from here.
}
1                                  ##1 will print current line here.
' Input_file  Input_file           ##Mentioning Input_file names here.

【讨论】:

    【解决方案3】:

    使用ed 编辑文件,而不是sed。它旨在与它们一起工作,例如将线条移动到文件中的任意位置:

    ed -s "$CSV_FILE" <<'EOF'
    /^Results:$/ka
    g/^Mean Pass Rate/m'a\
    ka
    w
    EOF
    

    这第一个标记kResults: 行,然后对于以 Mean Pass Rate 开头的每一行,m将该行移到标记之后并将标记点更改为最近移动的行(否则它们会以相反的顺序结束),然后w将修改后的文件重新写入磁盘。

    在带有两条平均通过率行的示例文件上运行它会导致它被编辑为:

    Unit Tests
    Model: A
    Tue Sep  8 22:52:24 MDT 2020
    User: br
    Files Used:
        DATA FILE - /path/to/file/data.txt
        TEST TARBALL - /path/to/tarball/my_test.tar.bz2
        CLIENT FILE - /path/to/other/file/client.txt
    
    Results:
    Mean Pass Rate for Client Tests,,27,27,0,100.00%
    Mean Pass Rate for All Tests,,64,53,11,82.81%
    
    Module,Test Suite,Total Tests,Tests Passed,Tests Failed,Pass Rate
    
    Individual Test Run,ClientTests,15,15,0,100.00%
    ,ClientVarTests,12,12,0,100.00%
    ,GraphTests,37,26,11,70.00%
    

    【讨论】:

      【解决方案4】:
      tac myFile | awk '
      /^Mean Pass Rate/ { move=(!move)?$0:move ORS $0;next }
      /^Results:/ { $0=move ORS $0 }
      1' - | tac
      

      【讨论】:

        猜你喜欢
        • 2012-02-10
        • 1970-01-01
        • 1970-01-01
        • 2013-10-08
        • 2013-11-09
        • 1970-01-01
        • 2018-08-25
        • 2023-01-24
        • 1970-01-01
        相关资源
        最近更新 更多