Shell-Script
我有四個文件,每個文件 10 行,如何獲得如下輸出
我有 4 個文件。我需要檢查所有文件的行數是否相等。
如果行數不同,我需要檢測並輸出,例如:
#file1 - 10 lines, file2 - 9 lines, file3 - 10 lines, file4 - 10 lines Line are miss matched Number of lines 10 = 9 = 10 = 10
如果它們相等,我想逐行合併文件,如下所示:
文件:
#file1 10 12 11 #file2 Arun kamal babu #file3 300 200 400 #file4 spot1 spot4 spot5
輸出:
Set1 10 Arun 300 spot1 Set2 12 kamal 200 spot4 Set3 11 babu 400 spot5
我的程式碼:
# id_name=`cat file2` echo $id_name id_list=`cat file1` echo $id_list # id_count=`cat file3` echo $id_count id_spot=`cat spot_list` echo $id_spot SS=`cat id_list | wc -l` DS=`cat id_name | wc -l` SF=`cat id_count | wc -l` DF=`cat id_spot | wc -l` if [ $SS == $DS == $SF == $DF ] then echo " Line are matched" echo " Total line $SS" for i j in $id_list $id_name do for a b in $id_count $id_spot do k = 1 echo " Set$k" $i $j $a $b done done else echo " Line are Miss matched" echo " Total line $SS = $DS = $SF = $DF" fi
採用非常直接的方法:
#!/usr/bin/env bash SS=$(wc -l < file1) DS=$(wc -l < file2) SF=$(wc -l < file3) DF=$(wc -l < file4) if [[ $SS -eq $DS && $DS -eq $SF && $SF -eq $DF ]]; then echo "Lines are matched" echo "Total number of lines: $SS" num=1 while (( num <= SS )); do echo "Set$num" tail -n +$num file1 | head -n 1 tail -n +$num file2 | head -n 1 tail -n +$num file3 | head -n 1 tail -n +$num file4 | head -n 1 ((num++)) echo done else echo "Line are miss matched" echo "Number of lines $SS = $DS = $SF = $DF" fi
它不是很有效,因為它呼叫
tail
4*number_of_lines 次,但它很簡單。另一種方法是將
while
循環替換為awk
:awk '{ printf("\nSet%s\n", NR) print; if( getline < "file2" ) print if( getline < "file3" ) print if ( getline < "file4" ) print }' file1
要逐行加入文件,該
paste
命令非常有用。您可以使用它來代替while
循環:paste -d$'\n' file1 file2 file3 file4
或者可能不那麼明顯:
{ cat -n file1 ; cat -n file2 ; cat -n file3; cat -n file4; } | sort -n | cut -f2-
這將輸出行但沒有格式(沒有 Set1、Set2、換行符、…),因此您必須在之後使用 格式化它
awk
,例如:awk '{ if ((NR-1)%4 == 0) printf("\nSet%s\n", (NR+3)/4) print }' < <(paste -d$'\n' file1 file2 file3 file4)
一些最後的筆記:
- 不要使用大寫變數,因為它們可能與環境和內部 shell 變數發生衝突
- 當您可以重定向輸入時不要使用
echo "$var" | cmd
或:或cat file | cmd``cmd <<< "$var"``cmd < file
for
循環中只能有一個變數名。for i in ...
是有效的,而for i j in ...
不是- 最好使用
[[ ]]
而不是[ ]
測試,請參閱此答案- 有很多方法可以做到這一點
- 這取決於您選擇使用哪種方法,但請注意效率差異:
的結果
time
,對 10000 行的文件進行了測試:#first approach real 0m45.387s user 0m5.904s sys 0m3.836s
#second approach - significantly faster real 0m0.086s user 0m0.024s sys 0m0.040s
#third approach - very close to second approach real 0m0.074s user 0m0.016s sys 0m0.036s