Bash 배열로 읽어야하는 file.txt가 있습니다. 그런 다음 공백, 큰 따옴표 및 모든 항목의 첫 번째 쉼표를 제외한 모든 항목 을 제거해야합니다. 내가 얼마나 멀리 왔는지 :
$ 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|
매개 변수 대체를 통해 가능합니까?
댓글
실제 프로그래밍 언어를 사용해야한다는 매우 좋은 표시입니다. 셸은 프로그래밍 언어로 설계되지 않았으며 하나로 사용할 수는 있지만 실제로는 ' 더 복잡한 작업에 적합하지 않습니다. perl이나 python 또는 다른 스크립팅 언어로 전환 할 것을 강력히 권합니다.
답변
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
댓글
- @JonRed 매개 변수가있는 버전을 추가했습니다. 대체하지만 ' 복잡하고 번거롭고보기 흉합니다. 셸에서 이런 종류의 작업을 수행하는 것은 아주 드물게 좋은 생각입니다.
- 공백과 큰 따옴표를 모두 제거한 경우 '이 문자를 사용할 수 있습니다.
RANDOMTEXTTHATWILLNEVERBEINTHEFILE
대신 사용합니다. - @Kusalananda 예, 방금 답변을 읽었습니다. 그것을 생각 했어야했다! 감사합니다 🙂
- 질문에 직접 답변하고 내가 선호하는 솔루션이 ' 이상적이지 않은 이유를 설명하고 가장 실행 가능한 대안을 제공합니다. 우수 답변입니다.
답변
내가 볼 수있는 한 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
는 2
및 g
의 조합을 명령).
코멘트
- GNU sed에서는
's/,//2g
를 사용할 수 있습니다. 쉼표를 제거하려면 두 번째로 시작 - 그리고 마지막 2 개의 s /// 명령은
s/.*/|ELEMENT|&|/
하지만 sed에게는 더 많은 노력이 필요할 수 있습니다. - @glennjackman 아마도 깔끔하게 보입니다.
- 예, 이것은 더 큰 대본의 일부입니다. 배열은 출력뿐만 아니라 필요합니다. 따라서 매개 변수 대체에 관심이 있습니다. 나는 이것으로 배열을 반복 할 수 있지만 구현하기에는 악몽이 될 것입니다. Terndon은 sed를 사용하여 루프가없는 솔루션을 제공했습니다. 매개 변수 대체가 중단되지 않으면 ' 대체 할 가능성이 높습니다.
- 그렇지 않은 경우 ' 배열 사용과 관련이 없지만 이것이 최상의 솔루션입니다.
답변
ELEMENT="50,n,e,e,d,2" IFS=, read -r first rest <<<"$ELEMENT" printf "%s,%s\n" "$first" "${rest//,/}"
50,need2
ALLCAPS 변수 이름을 사용하는 습관에서 벗어나십시오. 결국 PATH와 같은 중요한 “시스템”변수와 충돌하여 코드가 손상됩니다.
설명
- 매개 변수 대체가 아닙니다. 그러나 나는 ALLCAPS 변수 이름이 Bash에서 나쁜 습관이라는 것을 알지 못했습니다. 당신은 좋은 지적을하는데, 피상적 인 인터넷 검색이 확실히 확인하는 것입니다. 제 스타일을 개선 해주셔서 감사합니다! 🙂
- ' 그 사람이
PATH=something; ls $PATH
를 작성한 질문에 답변 한 다음ls: command not found
오류. - 모두 대문자로 명명 된 거의 100 개의 기본 제공 변수가 있습니다 (이 매뉴얼 페이지를 클릭하여 링크 ) 볼 수 있습니다 …
답변
[이것은 본질적으로 더 완벽하게 개발 된 glenn jackmann “s answer ]
첫 번째 쉼표를 구분 기호로 사용하여 제거 된 키와 값에서 연관 배열 만들기 :
declare -A arr while IFS=, read -r k v; do arr["${k//[ \"]}"]="${v//[ ,\"]}"; done < file.txt for k in "${!arr[@]}"; do printf "|ELEMENT|%s,%s|\n" "$k" "${arr[$k]}" done |ELEMENT|20,is| |ELEMENT|10,this| |ELEMENT|50,need2| |ELEMENT|40,I| |ELEMENT|60,see| |ELEMENT|30,all|
Answer
배열을 반복하고 중간 변수를 사용할 수 있습니다.
for((i=0; i < "${#ARRAY[@]}"; i++)) do rest="${ARRAY[i]#*,}" ARRAY[i]="${ARRAY[i]%%,*}","${rest//,/}" done
첫 번째 쉼표 뒤의 부분을 rest
에 할당 한 다음 세 부분을 다시 원본에 연결합니다. 변수 :
- 첫 번째 쉼표 앞 부분
- 쉼표
-
rest
의 모든 쉼표에서 아무것도없는 대체
댓글
- 이것은 저의 첫 번째 생각이었고 예제에서는 충분히 간단하지만 이것은 배열이 방대하고 이미 루프가 있고 ' 전체가되는 큰 스크립트의 일부입니다. 이것은 확실히 작동 할 것이지만 작업중인 더 큰 프로젝트에서 ' 구현하기에는 매우 번거 롭습니다.
- 충분합니다. 제한 범위 내에서 답변하려고했습니다 (매개 변수 확장 만 해당).
awk
또는sed
가 데이터를 처리합니까?