簡體   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