繁体   English   中英

使用 awk 或 sed 将文件中的特定行或多行移动到其他行的 Bash 脚本?

[英]Bash script to move specific line or lines in a file to other line with awk or sed?

我看到这里得到了回答: 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%

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

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

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

谢谢!

您可以使用 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%

您能否尝试在 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.

使用ed编辑文件,而不是sed 这意味着与他们一起工作,做一些事情,比如将行移动到文件中的任意位置:

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

该第一擦伤ķS中的结果:行,然后对每行开始与平均数的合格率oves该行到标记之后,并且改变标志点到最近移动线(否则他们会以相反的顺序结束),和则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%
tac myFile | awk '
/^Mean Pass Rate/ { move=(!move)?$0:move ORS $0;next }
/^Results:/ { $0=move ORS $0 }
1' - | tac

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM