탭을 구분 기호로 사용하여 bash에서 행을 배열로 분할

탭을 구분 기호로 사용하여 bash에서 행을 배열로 분할

탭으로 구분된 다음 형식의 파일이 있습니다.

a   k   testis  adult   male    8 week  rRNA
b   k   testis  adult   male    8 week  rRNA
c   k   testis  adult   male    8 week  rRNA

각 행에 대해 몇 가지 작업을 수행하고 싶기 때문에 while 루프를 사용합니다. 탭의 각 행을 분할한 다음 8 week여섯 번째 열로 간주되는 내용을 변수에 저장하고 싶습니다 . 이 코드를 사용하고 있지만 원하는 것을 얻을 수 없습니다

while read -r line; do tmp=(${line///}); col6=${tmp[5]}; echo "$col6"; done < file.txt

이것은 나에게 8또 다른 아니오를 제공합니다 8 week. 8주는 8과 주 사이에 공백이 있으므로 탭에서 행을 분할하고 싶습니다.

답변1

배열 할당은 기본적으로 탭을 포함하여 포함된 모든 문자 tmp=(${line///})로 값을 분할합니다 .IFS그리고 공간개행 문자. (빈 대체가 무엇인지 이해하지 못합니다.) 탭에서만 분할하려면 다음과 같이 설정하십시오 IFS.

foo=$'a\tk\testis\tadult\tmale\t8 week\tRNA'
IFS=$'\t'
tmp=($foo)
echo "${tmp[5]}"

여전히 와일드카드가 문제가 되고 이미 사용하고 있기 때문에 이를 기반으로 입력 줄을 분할 하고 결과 필드를 다음과 같이 저장하는 (Bash에서만 ksh/zsh/yash로 대체 ) 을 while read사용할 수 있습니다. 명명된 배열:read -a tmp-a-AIFS

$ while IFS=$'\t' read -r -a tmp ; do
    echo "${tmp[5]}"
done <<< $'a\tk\testis\tadult\tmale\t8 week\tRNA'

인쇄되었습니다 8 week. 또 다른 이점은 변경 사항이 스크립트의 나머지 부분이 아닌 IFS기간 동안에만 적용된다는 것입니다.read

그러나 read탭을 구분 기호로 사용하면 빈 필드가 제거됩니다. 에서는 를 교체 하여 이런 일이 발생하는 것을 방지 zsh할 수 있습니다 .IFS=$'\t'IFS=$'\t\t'

물론, 필드의 수/의미를 알고 있다면 read이를 별도의 명명된 변수로 나눌 수 있습니다.

... IFS=$'\t' read -r col1 col2 col3 ...

또는 이 열만 인쇄하려면 다음을 사용하세요 cut.

cut -d$'\t' -f 6  < file.txt

빈 열이 있고 cut -d$'\t'다른 IFS=$'\t'동작을 하는 경우. Cut은 각 개별 탭을 서로 다른 구분 기호로 처리하고 read연속 탭을 하나의 구분 기호로 처리합니다.하나의분할기. 즉, 문자열은 foo<tab><tab>bar두 개의 열로 읽히지 read만 세 개의 열로 읽히지는 않습니다 cut.

탭에 대한 설정은 변경할 수 없지만 인쇄 문자는 항상 다른 구분 기호로 인식되므로 데이터에 표시되지 않는 일부 문자로 탭을 변경한 다음 ... | tr '\t' : | IFS=: read -r -a tmp왼쪽, 오른쪽과 같은 구분 기호로 사용할 수 있습니다.

관련 정보