bash는 행을 열로 변환합니다.

bash는 행을 열로 변환합니다.

다음과 같은 수천 개의 파일이 있습니다.

조직 문서:

reference_group1 _CEFNB_
group1          ACBF_BG
group2          ACB_MBM
...

각 파일에 대해 행을 열로 변환한 다음 다음과 같이 reference_group의 인덱스로 구성된 열(id_from_reference_group이라고 함)을 추가해야 합니다.

변환된 파일


# explanation of each column
# reference_group_id    serials_from_ref_group  group_id    serials_from_group
reference_group1            _                group1            A
reference_group1                             group1            C
reference_group1            E                group1            B
reference_group1            F                group1            F
reference_group1            N                group1            _
reference_group1            B                group1            B
reference_group1            _                group1            G
reference_group1            _                group2            A
reference_group1            C                group2            C
reference_group1            E                group2            B
reference_group1            F                group2            _
reference_group1            N                group2            M
reference_group1            B                group2            B
reference_group1            _                group2            M

org_files의 각 그룹에 있는 두 번째 열의 내용은 반복되는 문자로 구성됩니다. 그리고 두 번째 열의 길이는 항상 동일합니다.

나는 노력했다

input="reference_group1 _CEFNB_
group1          ACBF_BG
group2          ACB_MBM"

while IFS=" " read -ra line; do # read input line by line
# loop over fields
  for (( i = 0 ; i < ${#line[@]}; i++ )); do
    # only split 2nd field
    if [[ $i == 1 ]]
    then
      for j in ${line[$i]}
      do
        # loopover each letter of 2nd field
        for (( j=0; j<${#line[$i]}; j++ ))
        do
          echo "${line[$i-1]}  ${line[$i]:$j:1}"
        done
      done
    fi

  done
done <<< "$input"

하지만 나는이 결과를 얻습니다

reference_group1  _
...
group1  A
...
group2  M

그리고 코드가 좀 지저분해요. 간단한 명령어가 있으면 더 좋을 것 같아요. 감사해요!

답변1

()와 같은 스크립트를 사용하여 awk를 사용할 수 있습니다 tst.awk.

BEGIN{print "#reference_group_id serials_from_ref_group group_id serials_from_group"}
$1 ~ /^reference_/ {ref=$1;ser=$2;next}
{
        for(i=1;i<=length($2);i++){
                print ref, substr(ser,i,1), $1, substr($2,i,1)
        }
}

내 생각에는 항상 reference_group_id먼저 reference_이름이 지정된 var에 저장한 ref다음 serials_from_ref_group에 저장합니다 ser. 그런 다음 루프에서 두 변수를 모두 사용합니다.

그러면 다음과 같은 줄이 작동합니다.

awk -f tst.awk file

출력 형식이 지정되면 column출력을 다음으로 파이프할 수 있습니다.column -t

awk -f tst.awk file | column -t

awk 스크립트에 대한 지침:

  • BEGIN첫 번째 입력 레코드 이전에 한 번만 실행됩니다.
  • $1 ~ /^reference_/$1정규 표현식과 일치하는 경우^reference_
  • length($2)두 번째 필드의 길이
  • substr(ser,i,1)ser위치와 길이 로 i시작하는 부분 문자열1

관련 정보