Bash 배열에서 매개변수 대체 사용

Bash 배열에서 매개변수 대체 사용

file.txt를 Bash 배열로 읽어야 합니다. 그런 다음 공백, 큰따옴표 및각 항목의 첫 번째 쉼표를 제외한 모든 것. 이것이 내가 얼마나 멀리 왔는지입니다:

$ cat file.txt
10,this
2 0 , i s
30,"all"
40,I
50,n,e,e,d,2
60",s e,e"

$ cat script.sh
#!/bin/bash
readarray -t ARRAY<$1
ARRAY=( "${ARRAY[@]// /}" )
ARRAY=( "${ARRAY[@]//\"/}" )
for ELEMENT in "${ARRAY[@]}";do
    echo "|ELEMENT|$ELEMENT|"
done

$ ./script.sh file.txt
|ELEMENT|10,this|
|ELEMENT|20,is|
|ELEMENT|30,all|
|ELEMENT|40,I|
|ELEMENT|50,n,e,e,d,2|
|ELEMENT|60,se,e|

이것은 쉼표를 제외하고는 훌륭하게 작동합니다. 이 고양이에 스킨을 적용하는 방법은 여러 가지가 있다는 것을 알고 있지만 이는 더 큰 스크립트의 일부이므로 여기에 도달하려면 매개변수 대체를 사용하고 싶습니다.

|ELEMENT|10,this|
|ELEMENT|20,is|
|ELEMENT|30,all|
|ELEMENT|40,I|
|ELEMENT|50,need2|
|ELEMENT|60,see|

매개변수 대체를 통해 이를 달성할 수 있습니까?

답변1

bash내가 아는 한, 해당 출력을 생성하기 위해 배열로 읽을 필요는 없습니다 .

$ sed 's/[ "]//g; s/,/ /; s/,//g; s/ /,/; s/.*/|ELEMENT|&|/' <file
|ELEMENT|10,this|
|ELEMENT|20,is|
|ELEMENT|30,all|
|ELEMENT|40,I|
|ELEMENT|50,need2|
|ELEMENT|60,see|

sed표현식은 공백과 큰따옴표를 제거하고, 첫 번째 쉼표를 공백으로 바꾸고(문자열에 다른 공백이 없는 경우), 다른 모든 쉼표를 제거하고, 첫 번째 쉼표를 복원하고, 추가 데이터를 앞에 추가합니다.

또는 GNU를 사용하십시오 sed.

sed 's/[ "]//g; s/,//2g; s/.*/|ELEMENT|&|/' <file

(표준 sed에서는 및 명령 플래그의 조합을 지원하지 않습니다.)2gs

답변2

제거해야 할 것을 제거하겠습니다.sed 앞으로배열로 로드(변수 이름도 소문자에 유의하세요. 일반적으로 쉘 스크립트에서는 대문자 변수를 피하는 것이 가장 좋습니다):

#!/bin/bash
readarray -t array< <(sed 's/"//g; s/  *//g; s/,/"/; s/,//g; s/"/,/' "$1")
for element in "${array[@]}";do
    echo "|ELEMENT|$element|"
done

그러면 예제 파일에 다음과 같은 출력이 생성됩니다.

$ foo.sh file 
|ELEMENT|10,this|
|ELEMENT|20,is|
|ELEMENT|30,all|
|ELEMENT|40,I|
|ELEMENT|50,need2|
|ELEMENT|60,see|

매개변수 대체를 꼭 사용해야 한다면 다음을 시도해 보세요.

#!/bin/bash
readarray -t array< "$1"
array=( "${array[@]// /}" )
array=( "${array[@]//\"/}" )
array=( "${array[@]/,/\"}" )
array=( "${array[@]//,/}" )
array=( "${array[@]/\"/,}" )

for element in "${array[@]}"; do
    echo "|ELEMENT|$element|"
done

답변3

ELEMENT='50,n,e,e,d,2'
IFS=, read -r first rest <<<"$ELEMENT"
printf "%s,%s\n" "$first" "${rest//,/}"
50,need2

변수 이름을 모두 대문자로 사용하는 습관을 버리세요. 결국 PATH와 같은 중요한 "시스템" 변수와 충돌하여 코드가 손상될 수 있습니다.

답변4

배열을 반복하고 중간 변수를 사용할 수 있습니다.

for((i=0; i < "${#ARRAY[@]}"; i++))
do
  rest="${ARRAY[i]#*,}"
  ARRAY[i]="${ARRAY[i]%%,*}","${rest//,/}"
done

그러면 첫 번째 쉼표 뒤의 부분에 할당됩니다 rest. 그런 다음 세 부분을 다시 원래 변수에 연결합니다.

  • 첫 번째 쉼표 앞 부분
  • 쉼표
  • rest각 쉼표를 공백으로 바꾸십시오.

관련 정보