Shell-Script

我有四個文件,每個文件 10 行,如何獲得如下輸出

  • December 4, 2017

我有 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

它不是很有效,因為它呼叫tail4*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

引用自:https://unix.stackexchange.com/questions/408536