source

bash 쉘에서 1개 이상의 공백으로 구분된 문자열을 여러 문자열로 분할하려면 어떻게 해야 합니까?

factcode 2023. 4. 9. 22:25
반응형

bash 쉘에서 1개 이상의 공백으로 구분된 문자열을 여러 문자열로 분할하려면 어떻게 해야 합니까?

나는 적어도 두 단어 사이에 한 칸씩 많은 단어를 포함하는 문자열을 가지고 있다.문자열을 개별 단어로 분할하여 루프할 수 있도록 하려면 어떻게 해야 합니까?

문자열은 인수로 전달됩니다.예.${2} == "cat cat file"어떻게 루프를 통과하지?

또한 문자열에 공백이 있는지 어떻게 확인할 수 있습니까?

개별 요소에 액세스할 수 있도록 어레이로 변환하는 것이 좋습니다.

sentence="this is a story"
stringarray=($sentence)

이제 개별 요소에 직접 액세스할 수 있습니다(0부터 시작).

echo ${stringarray[0]}

또는 다시 문자열로 변환하여 루프합니다.

for i in "${stringarray[@]}"
do
  :
  # do whatever on $i
done

물론 스트링을 통해 직접 루프하는 것은 이전에도 답한 적이 있지만, 이 답변에는 나중에 사용하기 위해 개별 요소를 추적하지 않는 단점이 있습니다.

for i in $sentence
do
  :
  # do whatever on $i
done

Bash 어레이 레퍼런스도 참조해 주세요.

문자열 변수를 전달하려고 했습니까?for예를 들어, Bash는 자동으로 공백으로 분할됩니다.

sentence="This is   a sentence."
for word in $sentence
do
    echo $word
done

 

This
is
a
sentence.

BASH 3 이상에서 가장 쉽고 안전한 방법은 다음과 같습니다.

var="string    to  split"
read -ra arr <<<"$var"

(어디서)arr는 문자열의 분할 부분을 차지하는 배열입니다.또는 입력에 새로운 행이 있을 수 있고 첫 번째 행보다 더 많은 행이 필요할 수 있습니다.

var="string    to  split"
read -ra arr -d '' <<<"$var"

(스페이스에 주의해 주세요.-d ''; 생략할 수 없습니다). 단, 이 경우 에서 예기치 않은 새로운 행이 표시될 수 있습니다.<<<"$var"(이것에 의해, 마지막에 LF가 암묵적으로 추가되기 때문에).

예:

touch NOPE
var="* a  *"
read -ra arr <<<"$var"
for a in "${arr[@]}"; do echo "[$a]"; done

예상 출력

[*]
[a]
[*]

이 솔루션(이전의 모든 솔루션과는 대조적으로)은 예기치 않게 제어 불가능한 셸글로빙이 발생하기 쉽지는 않기 때문입니다.

또, 다음과 같이, IFS 의 모든 기능을 이용할 수 있습니다.

예:

IFS=: read -ra arr < <(grep "^$USER:" /etc/passwd)
for a in "${arr[@]}"; do echo "[$a]"; done

출력은 다음과 같습니다.

[tino]
[x]
[1000]
[1000]
[Valentin Hilbig]
[/home/tino]
[/bin/bash]

보시는 바와 같이 공간도 이 방법으로 보존할 수 있습니다.

IFS=: read -ra arr <<<' split  :   this    '
for a in "${arr[@]}"; do echo "[$a]"; done

출력

[ split  ]
[   this    ]

주의하시기 바랍니다.IFSBASH 에서는, 그 자체가 대상입니다.테스트도 대상입니다.이것에 관한 몇개의 흥미로운 토픽이 있습니다.

  • unset IFS: SPC, TAB, NL 및 온라인 시작 및 종료 실행을 무시합니다.
  • IFS='': 필드를 구분하지 않고 모든 것을 읽습니다.
  • IFS=' ': SPC 실행(및 SPC만 해당)

마지막 예:

var=$'\n\nthis is\n\n\na test\n\n'
IFS=$'\n' read -ra arr -d '' <<<"$var"
i=0; for a in "${arr[@]}"; do let i++; echo "$i [$a]"; done

출력

1 [this is]
2 [a test]

하는 동안에

unset IFS
var=$'\n\nthis is\n\n\na test\n\n'
read -ra arr -d '' <<<"$var"
i=0; for a in "${arr[@]}"; do let i++; echo "$i [$a]"; done

출력

1 [this]
2 [is]
3 [a]
4 [test]

BTW:

  • 익숙하지 않은 경우$'ANSI-ESCAPED-STRING'익숙해져요. 시간 절약이 되죠.

  • 포함하지 않는 경우-r(예:read -a arr <<<"$var"그러면 read는 백슬래시가 이스케이프됩니다.이것은 독자를 위한 연습으로 남겨져 있다.


두 번째 질문:

나는 을 한다.case케이스를 할 수 있기 는 첫 일치만을 해, 폴 필요한 는, 복수의 「Multiple」(「Multiple」)를 합니다).case이치노이러한 요구는 매우 빈번하게 발생합니다(이러한 요구는,

case "$var" in
'')                empty_var;;                # variable is empty
*' '*)             have_space "$var";;        # have SPC
*[[:space:]]*)     have_whitespace "$var";;   # have whitespaces like TAB
*[^-+.,A-Za-z0-9]*) have_nonalnum "$var";;    # non-alphanum-chars found
*[-+.,]*)          have_punctuation "$var";;  # some punctuation chars found
*)                 default_case "$var";;      # if all above does not match
esac

따라서 다음과 같이 SPC를 검사하도록 반환 값을 설정할 수 있습니다.

case "$var" in (*' '*) true;; (*) false;; esac

★★★★case보통 regex 시퀀스보다 읽기 쉽고 Shell 메타캐릭터 덕분에 모든 요구의 99%를 매우 잘 처리할 수 있습니다.

내장된 쉘을 사용하면 됩니다.예를들면,

set $text

그 후 $text 내의 개별 단어는 $1, $2, $3 등이 됩니다.견고성을 위해 보통 다음과 같은 작업을 수행합니다.

set -- junk $text
shift

$text가 비어 있거나 대시로 시작하는 경우를 처리합니다.예를 들어 다음과 같습니다.

text="This is          a              test"
set -- junk $text
shift
for word; do
  echo "[$word]"
done

이 인쇄물은

[This]
[is]
[a]
[test]
$ echo "This is   a sentence." | tr -s " " "\012"
This
is
a
sentence.

공간을 확인하려면 grep를 사용합니다.

$ echo "This is   a sentence." | grep " " > /dev/null
$ echo $?
0
$ echo "Thisisasentence." | grep " " > /dev/null     
$ echo $?
1
echo $WORDS | xargs -n1 echo

그러면 모든 단어가 출력되므로 나중에 적합하다고 판단되는 대로 목록을 처리할 수 있습니다.

(A) 문장을 해당 단어로 분할하려면(공백으로 구분됨) 기본 IFS를 사용하면 됩니다.

array=( $string )


다음 스니펫을 실행하는 예

#!/bin/bash

sentence="this is the \"sentence\"   'you' want to split"
words=( $sentence )

len="${#words[@]}"
echo "words counted: $len"

printf "%s\n" "${words[@]}" ## print array

will 출력

words counted: 8
this
is
the
"sentence"
'you'
want
to
split

할 수 .

★★★★★★★
--이것은 기본적으로 mob의 답변과 동일하지만, 이러한 방법으로 어레이를 보존해 두면, 한층 더 필요하게 됩니다.루프가 1개만 필요한 경우는, 1 행 짧게 하는 그의 회답을 사용할 수 있습니다.
-- 딜리미터에 근거해 문자열을 분할하는 대체 방법에 대해서는, 이 질문을 참조해 주세요.


(B) 문자열 내의 문자를 확인하려면 정규 표현 일치를 사용할 수도 있습니다.
사용할 수 있는 공백 문자가 있는지 확인하는 예:

regex='\s{1,}'
if [[ "$sentence" =~ $regex ]]
    then
        echo "Space here!";
fi

bash만으로 공간을 확인하는 경우:

[[ "$str" = "${str% *}" ]] && echo "no spaces" || echo "has spaces"

echo foo bar baz | sed 's/ /\n/g'

foo
bar
baz

제 사용 사례에서 가장 좋은 옵션은 다음과 같습니다.

grep -oP '\w+' file

기본적으로 이것은 연속된 공백이 아닌 문자와 일치하는 정규 표현입니다.즉, 모든 유형과 공백의 양이 일치하지 않습니다.-o 파라미터는 각 워드가 다른 행에서 일치하는 것을 출력합니다.

이에 대한 또 다른 견해(Perl 사용):

$ echo foo bar baz | perl -nE 'say for split /\s/'
foo
bar
baz

언급URL : https://stackoverflow.com/questions/1469849/how-to-split-one-string-into-multiple-strings-separated-by-at-least-one-space-in

반응형