IFS를 다른 값으로 설정하는 배열 생성

IFS를 다른 값으로 설정하는 배열 생성

배열을 구성하여 이 형식으로 파일에 쓰려고 합니다. 즉, 파일 내용은 다음과 같아야 합니다.

hero_pairscore=( askdjfh sdf,sdlkfj lksf,dfgdf,dsflkgj,asdlkf ....)

여기서 요소는 으로 구분됩니다 comma. 이를 위해 다음 코드를 작성했습니다.

#!/bin/bash
#set -x

hero_pairscore=()
while read line
do

$( IFS=",";hero_pairscore+=( "$line" )
done < true_pairscore.txt

echo "hero_pairscore=( ${hero_pairscore[@]} )" > embed.txt

하지만 생성된 파일에는 이 내용만 포함되어 있습니다 hero_pairscore=( ). 내 코드에 어떤 문제가 있으며 원하는 출력을 제공하려면 어떻게 수정해야 합니까?

답변1

여기서 해야 할 일은 다음과 같습니다.

  1. 변수를 설정합니다. 우리는 이것을 사용할 것입니다:

    var="kijhg, fbjhku,,,ioy  fbjfr, kjmyhg"
    
  2. 파일 이름 확장 설정 $IFS및 방지:

    IFS=, ; set -f
    
  3. set출력할 쉘 배열 $@.

    set -- $var
    
  4. 상위 셸 $IFS및 셸 매개변수를 재설정합니다.

    unset IFS ; set +f
    
  5. 오랫동안 살다! 여러 반복과 공백 등도 보존합니다!

    printf %s\\n "$@"
    

    산출

    kijhg
     fbjhku
    
    
    ioy  fbjfr
     kjmyhg
    

어쨌든 내 말을 들어주세요. a가 아닌 모든 문자는 ,유지됩니다.

전환하다

특히 bash 배열 대신 실제 쉘 배열을 사용하는 것이 좋습니다. 왜냐하면 즉시 스플리터로 변환할 수 있기 때문입니다.

printf %s "$*"

#OUTPUT#
kijhg  fbjhku   ioy  fbjfr  kjmyhg %

IFS=, ; printf %s "$*"

#OUTPUT#
kijhg, fbjhku,,,ioy  fbjfr, kjmyhg

$*첫 번째 문자에서 셸의 위치 인수 배열을 분할하는 특별한 POSIX 지정 품질로 인해 $IFS많은 양의 데이터를 쉽게 변환할 수 있습니다. "quote"매개변수 배열을 보호하면서도 원하는 단일 문자로 분할 할 수 있습니다 . 처음에 제대로만 하면 됩니다.

추가/접두사

POSIX는 또한 이에 대한 특별한 속성을 지정합니다 "$@". "$1"... eval "\${$#}"각 인수의 주소 지정 형식 외에도 인수 "$@"(인용된 경우) set는 의 현재 값에 관계없이 마지막 인수이므로 모든 셸 인수로 안전하게 확장할 수 있습니다. $IFS.따라서 배열의 시작 부분에 목록을 추가하려면 다음을 수행할 수 있습니다.

set -- $list "$@"

머리/꼬리 방향:

set -- $head "$@" $tail

배열을 3배로 늘리려면:

set -- "$@" "$@" "$@"

현재 합계

데이터 흐름이 매우 크지 않은 한 다음 작업은 현재 작업보다 약간 더 빠를 수 있습니다.(그러나 파일 작업을 하는 경우 쉘 분할을 완전히 피하는 것이 가장 좋습니다):

( set -f -- ; IFS=, ; while read -r line ; do set -- "$@" $line ; done
printf %s "$*" ) | cat >out

어쩌면 TR?

하지만 내가 이해하지 못하는 것은 – 당신은 무엇을 하고 있나요? 개행 문자를 쉼표로 바꾸시겠습니까? 내 말은 -데이터가 이미 개행 문자 외에 쉼표로 구분되어 있습니까?만일이 경우라면:

tr '\n' ',' <in >out

답변2

내가 해야 할 일을 해라생각하다당신이 하려는 일은 쉼표로 구분된 각 필드를 true_pairscore.txt배열 변수로 읽는 것입니다. 코드에는 큰 문제가 없습니다. 해당 줄 $(의 시작 부분이 IFS분명히 잘못되어 스크립트에 오류가 발생하게 됩니다(아마도 이것이 출력이 없는 이유일 것입니다). 그 외에 코드의 주요 수정 사항은 단어 분할을 $line원하기 때문에 주변 따옴표를 제거하는 것입니다 (일반적으로 이를 방지하기 위해 사용합니다).bashIFS

#!/bin/bash

set -o noglob
OIFS=$IFS
IFS=","
hero_pairscore=()

while IFS= read -r line
do
  hero_pairscore+=( $line )
done < true_pairscore.txt

echo "hero_pairscore=( ${hero_pairscore[@]} )" > embed.txt

set +o noglob
IFS=$OIFS

그러나 위의 작업을 단 두 줄로 수행하는 방법은 다음과 같습니다.

IFS=$',\n' read -ra hero_pairscore -d '' <true_pairscore.txt
echo "hero_pairscore=( ${hero_pairscore[@]} )" > embed.txt

고쳐 쓰다

embed.txt다른 쉘에서 파일을 가져오려면 배열 에 기록된 각 요소를 bash인용해야 할 수도 있습니다 . hero_pairscore이렇게 하려면 echo "hero_pairscore=( ${hero_pairscore[@]} )"다음으로 바꾸세요.

echo "hero_pairscore=( $(printf '"%s" ' "${hero_pairscore[@]}") )"

관련 정보