![4개의 파일이 있고 각 파일에는 10줄이 있습니다. 다음 출력을 어떻게 얻을 수 있습니까?](https://linux55.com/image/122968/4%EA%B0%9C%EC%9D%98%20%ED%8C%8C%EC%9D%BC%EC%9D%B4%20%EC%9E%88%EA%B3%A0%20%EA%B0%81%20%ED%8C%8C%EC%9D%BC%EC%97%90%EB%8A%94%2010%EC%A4%84%EC%9D%B4%20%EC%9E%88%EC%8A%B5%EB%8B%88%EB%8B%A4.%20%EB%8B%A4%EC%9D%8C%20%EC%B6%9C%EB%A0%A5%EC%9D%84%20%EC%96%B4%EB%96%BB%EA%B2%8C%20%EC%96%BB%EC%9D%84%20%EC%88%98%20%EC%9E%88%EC%8A%B5%EB%8B%88%EA%B9%8C%3F.png)
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 | cmd
cmd <<< "$var"
cmd < file
for
루프에는 변수 이름이 하나만 있을 수 있습니다.for i in ...
유효, 그렇지 않으면for i j in ...
유효하지 않음[[ ]]
테스트하는 것 보다 사용하는 것이 더 좋습니다[ ]
. 이것을 참조하십시오답변- 하나 있다많은이를 수행하는 방법
- 사용할 방법을 선택할 수 있지만 효율성 차이에 유의하세요.
time
10,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
입력 필드 구분 기호를 출력 필드 구분 기호로 변환하는 데 사용됩니다.