Unix 스크립트는 파일의 첫 번째 줄을 읽은 후 종료됩니다.

Unix 스크립트는 파일의 첫 번째 줄을 읽은 후 종료됩니다.

파일의 한 줄당 탭 수를 계산하고 조건이 일치하면 해당 줄을 다른 파일에 인쇄하려고 합니다. 그러나 스크립트는 첫 번째 줄만 읽고 종료됩니다.

아래에서 무엇이 문제인지 알려주세요.

#!/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 $0FS

파일에서 텍스트 줄을 추출하고 이를 루프의 유사한 도구로 전달하거나 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

관련 정보