bash / cut / split을 사용하여 문자열의 일부 추출


121

다음과 같은 문자열이 있습니다.

/var/cpanel/users/joebloggs:DNS9=domain.com

joebloggs이 문자열에서 사용자 이름 ( ) 을 추출하여 변수에 저장해야합니다.

문자열의 형식은 항상 제외와 동일합니다 joebloggsdomain.com그래서 사용하여 두 번 문자열을 분할 할 수 있습니다 생각하고있다 cut?

첫 번째 분할은 분할되고 :첫 번째 부분을 변수에 저장하여 두 번째 분할 함수에 전달합니다.

두 번째 분할은 /마지막 단어 ( joebloggs)로 분할되어 변수에 저장됩니다.

배열과 분할을 사용하여 PHP에서 이것을 수행하는 방법을 알고 있지만 bash에서는 약간 길을 잃었습니다.

답변:


333

joebloggs추가 프로세스없이 매개 변수 확장을 사용하여 bash에서이 문자열 을 추출하려면 ...

MYVAR="/var/cpanel/users/joebloggs:DNS9=domain.com" 

NAME=${MYVAR%:*}  # retain the part before the colon
NAME=${NAME##*/}  # retain the part after the last slash
echo $NAME

joebloggs경로의 특정 깊이에있는 것에 의존하지 않습니다 .


요약

참조를 위해 몇 가지 매개 변수 확장 모드에 대한 개요 ...

${MYVAR#pattern}     # delete shortest match of pattern from the beginning
${MYVAR##pattern}    # delete longest match of pattern from the beginning
${MYVAR%pattern}     # delete shortest match of pattern from the end
${MYVAR%%pattern}    # delete longest match of pattern from the end

따라서 #처음부터 일치를 의미하고 (주석 줄을 생각해보십시오) %끝부터 의미합니다. 하나의 인스턴스는 가장 짧은 것을 의미하고 두 개의 인스턴스는 가장 긴 것을 의미합니다.

숫자를 사용하여 위치에 따라 부분 문자열을 얻을 수 있습니다.

${MYVAR:3}   # Remove the first three chars (leaving 4..end)
${MYVAR::3}  # Return the first three characters
${MYVAR:3:5} # The next five characters after removing the first 3 (chars 4-9)

다음을 사용하여 특정 문자열 또는 패턴을 바꿀 수도 있습니다.

${MYVAR/search/replace}

pattern파일 이름 일치 동일한 포맷이므로, *(모든 자)들은 같은 특정 기호 뒤에 공통 /또는.

예 :

다음과 같은 변수가 주어지면

MYVAR="users/joebloggs/domain.com" 

파일 이름을 남기는 경로를 제거하십시오 (슬래시까지의 모든 문자) :

echo ${MYVAR##*/}
domain.com

경로를 남겨두고 파일 이름을 제거합니다 (마지막 일치 후 가장 짧은 일치 항목 삭제 /).

echo ${MYVAR%/*}
users/joebloggs

파일 확장자 만 가져옵니다 (마지막 기간 이전에 모두 제거).

echo ${MYVAR##*.}
com

참고 : 두 작업을 수행하려면 두 작업을 결합 할 수 없지만 중간 변수에 할당해야합니다. 따라서 경로 나 확장자없이 파일 이름을 얻으려면 :

NAME=${MYVAR##*/}      # remove part before last slash
echo ${NAME%.*}        # from the new var remove the part after the last period
domain

이것이 grep의 창의적인 사용에 대한 주장인지 반대인지 확실하지 않지만 VAR = / here / is / a / path : with / a / colon / inside : DNS9 = domain.com
rici

2
단! 그리고 실행중인 셸 내에서 수행되므로 다른 명령을 사용하는 것보다 훨씬 빠릅니다.
stolsvik

3
@Fadi 당신은 콜론 앞에 오는 와일드 카드를 전환 할 수 있고, 사용하는 #대신 %. 맨 마지막 콜론 뒤의 부분 만 원하는 경우 ${MYVAR##*:}첫 번째 콜론 뒤의 부분을 가져 오려면 사용하십시오.${MYVAR#*:}
beroe

4
친구여, 제가이 답변에 몇 번이나 돌아 왔는지 모릅니다. 감사합니다!
Joel B

1
좋은 대답입니다! 질문 : 내 패턴이 변수 인 경우 이와 같이 입력합니까, ${RET##*$CHOP}아니면 이와 같이 입력 ${RET##*CHOP}합니까 (또는 다른 방법)? 편집 : 전자 인 것 같습니다${RET##*$CHOP}
Ctrl S

43

다음과 같이 함수를 정의하십시오.

getUserName() {
    echo $1 | cut -d : -f 1 | xargs basename
}

그리고 문자열을 매개 변수로 전달합니다.

userName=$(getUserName "/var/cpanel/users/joebloggs:DNS9=domain.com")
echo $userName

1
이 대답은 내가 여기에 온 것을 성취하는 데 도움이되었습니다. 수락 된 답변이 없으며 이것은 단순성에 대한 내 투표를 얻습니다.
harperville

1
위의 명령에서해야 할 유일한 수정은 다음과 같이 ':'을 제거하는 것 echo $1 | cut -d -f 1 | xargs입니다. 간단하고 깔끔한 ans를위한 +1.
Bhushan

20

sed는 어떻습니까? 단일 명령으로 작동합니다.

sed 's#.*/\([^:]*\).*#\1#' <<<$string
  • #대신 정규식 분할에 사용되는 /문자열이 있기 때문에 /거기에.
  • .*/ 마지막 백 슬래시까지 문자열을 잡습니다.
  • \( .. \)캡처 그룹을 표시합니다. 이것은입니다 \([^:]*\).
    • [^:]콜론 _except 모든 문자를 말합니다, 그리고 *수단은 0 개 이상.
  • .* 나머지 줄을 의미합니다.
  • \1첫 번째 (유일한) 캡처 그룹에서 발견 된 것을 대체하는 것을 의미합니다. 이것이 이름입니다.

다음은 정규 표현식과 일치하는 문자열을 분석 한 것입니다.

        /var/cpanel/users/           joebloggs  :DNS9=domain.com joebloggs
sed 's#.*/                          \([^:]*\)   .*              #\1       #'

슈퍼 멋진 해부!
kyb

11

단일 sed 사용

echo "/var/cpanel/users/joebloggs:DNS9=domain.com" | sed 's/.*\/\(.*\):.*/\1/'

10

단일 Awk 사용 :

... | awk -F '[/:]' '{print $5}'

즉, 필드 분리 중 하나로 사용된다 /또는 :사용자 이름 필드 5 항상.

변수에 저장하려면 :

username=$(... | awk -F '[/:]' '{print $5}')

sed사용자 이름이 필드 5 일 필요가없는 보다 유연한 구현 :

... | sed -e s/:.*// -e s?.*/??

즉, :이후의 모든 항목을 삭제 한 다음 마지막 /. sed아마도보다 빠르기 awk때문에이 대안이 확실히 낫습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.