[string] Bash에서 부분 문자열 추출

형식의 파일 이름이 주어지면 someletters_12345_moreleters.ext5 자리를 추출하여 변수에 넣고 싶습니다.

요점을 강조하기 위해 x 개의 문자를 가진 파일 이름을 가진 다음 5 개의 문자 시퀀스를 한쪽의 밑줄로 묶은 다음 x 개의 문자 세트로 묶습니다. 5 자리 숫자를 가져 와서 변수에 넣고 싶습니다.

이 작업을 수행 할 수있는 다양한 방법에 관심이 있습니다.



답변

사용 :

echo 'someletters_12345_moreleters.ext' | cut -d'_' -f 2

더 일반적인 :

INPUT='someletters_12345_moreleters.ext'
SUBSTRING=$(echo $INPUT| cut -d'_' -f 2)
echo $SUBSTRING


답변

경우 X는 상수 추출 부분 문자열 다음 파라미터 확장 행한다이다 :

b=${a:12:5}

여기서 12 는 오프셋 (0부터 시작)이고 5 는 길이입니다.

숫자 주위의 밑줄이 입력의 유일한 밑줄 인 경우 접두사와 접미사를 (각각) 두 단계로 제거 할 수 있습니다.

tmp=${a#*_}   # remove prefix ending in "_"
b=${tmp%_*}   # remove suffix starting with "_"

다른 밑줄이 있다면 어쩌면 더 어려울 수도 있지만 아마도 가능할 것입니다. 누구든지 단일 표현으로 두 확장을 수행하는 방법을 알고 있다면 나도 알고 싶습니다.

제시된 두 솔루션 모두 프로세스 생성이 필요하지 않은 순수한 bash이므로 매우 빠릅니다.


답변

해당 시퀀스 중 첫 번째 시퀀스를 사용하여 파일 이름의 어느 위치 에나있을 수있는 일반적인 솔루션 :

number=$(echo $filename | egrep -o '[[:digit:]]{5}' | head -n1)

변수의 일부를 정확히 추출하는 또 다른 솔루션 :

number=${filename:offset:length}

파일 이름이 항상 형식 인 stuff_digits_...경우 awk를 사용할 수 있습니다.

number=$(echo $filename | awk -F _ '{ print $2 }')

숫자를 제외한 모든 것을 제거하는 또 다른 해결책은

number=$(echo $filename | tr -cd '[[:digit:]]')


답변

그냥 사용하려고 cut -c startIndx-stopIndx


답변

누군가가 더 엄격한 정보를 원한다면 다음과 같이 man bash에서 검색 할 수 있습니다

$ man bash [press return key]
/substring  [press return key]
[press "n" key]
[press "n" key]
[press "n" key]
[press "n" key]

결과:

$ {parameter : offset}
       $ {parameter : offset : 길이}
              부분 문자열 확장. 최대 길이의 문자까지 확장
              오프셋으로 지정된 문자에서 시작하는 매개 변수. 만약
              길이가 생략되고 매개 변수 시작의 하위 문자열로 확장됩니다.
              오프셋으로 지정된 문자를 참조하십시오. 길이와 오프셋은
              산술 표현식 (아래의 산술 평가 참조). 만약
              오프셋은 0보다 작은 숫자로 평가되며 값이 사용됩니다
              매개 변수 값의 끝에서 오프셋으로. 산수
              -로 시작하는 표현식은 공백으로 구분해야합니다.
              앞의 : 사용 기본값과 구별
              가치 확장. 길이가 다음보다 작은 수로 평가되는 경우
              0이며 매개 변수가 @가 아니며 색인 또는 연관이 아닙니다.
              배열은 값의 끝에서 오프셋으로 해석됩니다.
              여러 문자가 아닌 매개 변수와 확장
              sion은 두 오프셋 사이의 문자입니다. 매개 변수가
              @, 결과는 off에서 시작하는 길이 위치 매개 변수입니다.
              세트. parameter가 @ 또는 아래로 첨자 화 된 인덱스 배열 이름 인 경우
              *, 결과는 다음으로 시작하는 배열의 길이 멤버입니다.
              $ {parameter [offset]}. 음수 오프셋은
              지정된 배열의 최대 인덱스보다 큰 1 보결-
              연관 배열에 적용된 문자열 확장은 unde-
              벌금 결과. 음수 오프셋을 분리해야합니다.
              혼동을 피하기 위해 적어도 하나의 공간만큼 결장에서
              :-확장으로. 하위 문자열 인덱싱은 0부터 시작합니다.
              위치 매개 변수가 사용되며이 경우 색인 작성
              기본적으로 1에서 시작합니다. 오프셋이 0이고 위치가
              매개 변수가 사용되면 $ 0이 목록 앞에 붙습니다.


답변

내가하는 방법은 다음과 같습니다.

FN=someletters_12345_moreleters.ext
[[ ${FN} =~ _([[:digit:]]{5})_ ]] && NUM=${BASH_REMATCH[1]}

설명:

배쉬 특정 :

정규 표현식 (RE) : _([[:digit:]]{5})_

  • _ 일치하는 문자열의 경계를 구분 / 고정하기위한 리터럴입니다.
  • () 캡처 그룹 만들기
  • [[:digit:]] 캐릭터 클래스라고 생각합니다.
  • {5} 이전 문자, 클래스 (이 예에서와 같이) 또는 그룹 중 정확히 5 개가 일치해야 함을 의미합니다.

영어로, 당신은 다음과 같이 행동 할 수 있습니다 : FN문자열은 우리가 볼 때까지 문자별로 반복됩니다_ 캡처 그룹이 열리는 지점을 5 자리를 맞추려고합니다. 일치하는 지점이이 지점에 도달하면 캡처 그룹은 이동 된 5 자리 숫자를 저장합니다. 다음 문자가 _인 경우 조건이 성공하고에서 캡처 그룹을 사용할 수 있으며 BASH_REMATCH다음 NUM=명령문을 실행할 수 있습니다. 일치하는 부분이 실패하면 저장된 세부 정보가 삭제되고 _. 예를 들어 FNwhere _1 _12 _123 _1234 _12345_인 경우 일치하는 항목을 찾기 전에 네 개의 잘못된 시작이 발생합니다.


답변

이 순수한 bash 솔루션이 나타나지 않았다는 것에 놀랐습니다.

a="someletters_12345_moreleters.ext"
IFS="_"
set $a
echo $2
# prints 12345

IFS를 이전 또는 unset IFS이후의 값으로 재설정하려고합니다 .