파일의 한 줄당 탭 수를 계산하고 조건이 일치하면 해당 줄을 다른 파일에 인쇄하려고 합니다. 그러나 스크립트는 첫 번째 줄만 읽고 종료됩니다.
아래에서 무엇이 문제인지 알려주세요.
#!/bin/bash
set -e
set -o pipefail
filename="0101.tsv"
while IFS= read -r line;do
s=$(awk '{print gsub(/\t/,"")}')
echo $s
if [[ $s -eq 995 ]]; then
printf "%s\n" "$line"
continue
fi
done < $filename > abc.tsv
감사해요! .
답변1
파일에서 탭으로 구분된 필드 수를 계산하려는 것 같습니다. 이렇게 하려면 탭에서 입력 라인을 분할하고 개수를 계산해야 합니다. awk
이는 자동으로 수행될 수 있으며 결과 필드 수에 대한 특수 변수도 있습니다 NF
.
996개 필드(995개 라벨)가 포함된 모든 행을 인쇄하려는 경우:
awk -F '\t' 'NF == 996' <file
이는 단축된 방법입니다.
awk 'BEGIN { FS = "\t" } NF == 996 { print }' <file
즉, 입력 레코드(행) 인쇄를 print
의미하는 것은 입력 필드 구분 기호입니다.print $0
FS
파일에서 텍스트 줄을 추출하고 이를 루프의 유사한 도구로 전달하거나 awk
이를 sed
통해 전달할 때마다 항상 동일한 작업을 수행하는 더 효율적인 방법이 있습니다. 위 명령은 awk
한 번만 호출되는 반면, 솔루션(데이터를 올바르게 전달한 경우 )은 파일의 모든 줄 awk
에 대해 호출됩니다 .awk
답변2
@steeldriver의 oneliner가 awk
작업을 수행할 수 있지만 bash 쉘스크립트로 행을 읽으려면 다음을 수행할 수 있습니다.
#!/bin/bash
set -e
set -o pipefail
filename="0101.tsv"
while IFS= read -r line
do
s=0
len=${#line}
# echo "line=$line"
# echo "len=$len"
for (( i=0; i<$len; i++ ))
do
if [ "${line:i:1}" == $'\t' ]
then
s=$((s +1))
fi
done
echo $s
if [[ "$s" == "995" ]]; then
printf "%s\n" "$line"
continue
fi
done < "$filename" > abc.tsv