4개의 파일이 있고 각 파일에는 10줄이 있습니다. 다음 출력을 어떻게 얻을 수 있습니까?

4개의 파일이 있고 각 파일에는 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

답변1

아주 간단한 방법으로:

#!/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

4*number_of_lines 번 호출하므로 그다지 효율적이지는 않지만 tail간단합니다.


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)

몇 가지 최종 참고사항:

  • 환경 및 내부 쉘 변수와 충돌할 수 있으므로 대문자 변수를 사용하지 마십시오.
  • 입력을 리디렉션할 수 있는 경우 또는 를 사용하지 마세요 echo "$var" | cmd. 또는cat file | cmdcmd <<< "$var"cmd < file
  • for루프에는 변수 이름이 하나만 있을 수 있습니다. for i in ...유효, 그렇지 않으면 for i j in ...유효하지 않음
  • [[ ]]테스트하는 것 보다 사용하는 것이 더 좋습니다 [ ]. 이것을 참조하십시오답변
  • 하나 있다많은이를 수행하는 방법
  • 사용할 방법을 선택할 수 있지만 효율성 차이에 유의하세요.

time10,000줄 파일에서 테스트한 결과:

#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

답변2

파일당 줄 수를 확인하는 방법을 알 수 있습니다. (힌트 wc:)

컬렉션의 출력을 얻으려면 다음을 수행하십시오.

paste File{1,2,3,4} | awk -F'\t' -v OFS='\n' '{$1=$1; print "Set"NR, $0, ""}'

$1=$1입력 필드 구분 기호를 출력 필드 구분 기호로 변환하는 데 사용됩니다.

관련 정보