Bash에서 하위 문자열 추출
이 " 에파이지정됨이름일양식▁a" someletters_12345_moreleters.ext저는 5자리 숫자를 추출하여 변수에 넣고 싶습니다.
이 점을 강조하기 위해 파일 이름에 x자 수, 양쪽에 하나의 밑줄로 둘러싸인 5자리 순서, 다른 x자 수를 사용합니다.저는 5자리 숫자를 가지고 변수에 넣고 싶습니다.
저는 이것이 달성될 수 있는 다양한 방법에 매우 관심이 있습니다.
매개 변수 확장을 사용하여 이 작업을 수행할 수 있습니다.
a가 일정한 경우 다음 파라미터 확장은 하위 문자열 추출을 수행합니다.
b=${a:12:5}
여기서 12는 오프셋(제로 기반)이고 5는 길이입니다.
숫자 주위의 밑줄이 입력에 있는 유일한 밑줄인 경우 다음 두 단계로 접두사와 접미사를 각각 제거할 수 있습니다.
tmp=${a#*_} # remove prefix ending in "_"
b=${tmp%_*} # remove suffix starting with "_"
다른 밑줄이 있다면 더 까다롭지만 어쨌든 실현 가능할 것입니다.두 확장을 모두 하나의 표현으로 수행하는 방법을 아는 사람이 있다면 저도 알고 싶습니다.
제시된 두 솔루션 모두 프로세스 생성이 수반되지 않는 순수한 bash이므로 매우 빠릅니다.
잘라내기 사용:
echo 'someletters_12345_moreleters.ext' | cut -d'_' -f 2
더 일반적인 것:
INPUT='someletters_12345_moreleters.ext'
SUBSTRING=$(echo $INPUT| cut -d'_' -f 2)
echo $SUBSTRING
그냥사보세요해용요를 사용해 보세요.cut -c startIndx-stopIndx
다음 시퀀스 중 첫 번째 시퀀스를 사용하여 파일 이름의 임의 위치에 숫자가 있을 수 있는 일반 솔루션:
number=$(echo $filename | egrep -o '[[:digit:]]{5}' | head -n1)
변수의 일부를 정확하게 추출하는 또 다른 솔루션:
number=${filename:offset:length}
의 형식이 ▁format인 경우stuff_digits_...awk:▁awk를 사용할 수 .
number=$(echo $filename | awk -F _ '{ print $2 }')
그러나 숫자를 제외한 모든 것을 제거하는 또 다른 솔루션, 사용
number=$(echo $filename | tr -cd '[[:digit:]]')
다음과 같은 방법이 있습니다.
FN=someletters_12345_moreleters.ext
[[ ${FN} =~ _([[:digit:]]{5})_ ]] && NUM=${BASH_REMATCH[1]}
설명:
Bash 관련:
[[ ]]조건식을 나타냅니다.=~조건이 정규식임을 나타냅니다.&&이전 명령이 성공한 경우 명령을 연결합니다.
정식규(RE):_([[:digit:]]{5})_
_입니다.()그룹[[:digit:]]캐릭터 클래스입니다, 저는 그것이 스스로를 설명한다고 생각합니다.{5}의 문자,) 중 해야 함을 합니다.
과 같이 할 수 : 영로어이, 당신이이행생수있고다습니각할다:FN문자열은 우리가 볼 때까지 문자별로 반복됩니다._캡처 그룹이 열리고 5자리 숫자를 일치시키려고 합니다.이 지점까지 일치하면 캡처 그룹은 통과된 5자리 숫자를 저장합니다.다음 문자가 다음 문자인 경우_이고, 은 조이성그사수있용다습니할룹건을로 사용 가능합니다.BASH_REMATCH 그다의음.NUM=문을 실행할 수 있습니다. 정보는 됩니다._예를 들어FN_1 _12 _123 _1234 _12345_일치하는 것을 발견하기 전에 네 번의 잘못된 출발이 있을 것입니다.
누군가가 더 엄격한 정보를 원할 경우, 당신은 또한 다음과 같이 맨배시에서 검색할 수 있습니다.
$ man bash [press return key]
/substring [press return key]
[press "n" key]
[press "n" key]
[press "n" key]
[press "n" key]
결과:
${매개 변수:vmdk}${parameter:parameter:length}부분 문자열 확장.의 최대 길이 문자로 확장됩니다.간격띄우기로 지정된 문자로 시작하는 매개 변수입니다.한다면길이가 생략됨, 매개변수 시작의 하위 문자열로 확장됨 »간격띄우기로 지정된 문자에 대해 입력합니다.길이와 간격띄우기는산술 표현식(아래 산술 평가 참조).한다면오프셋은 0보다 작은 숫자로 평가되며, 값이 사용됩니다.파라미터 값의 끝에서 오프셋으로 사용합니다.산술a로 시작하는 식은 공백으로 구분해야 합니다.앞에서 : 기본값 사용과 구별됨가치 확장.길이가 다음보다 작은 숫자로 평가되는 경우0, 매개 변수가 @가 아니며 인덱스 또는 연관성이 없습니다.배열, 값의 끝에서 오프셋으로 해석됩니다.문자 수보다 매개 변수의 수와 확장 »sion은 두 오프셋 사이의 문자입니다.매개 변수가 다음과 같은 경우결과는 off에서 시작하는 길이 위치 매개변수입니다.세트.매개 변수가 인덱스 배열 이름인 경우 @ 또는결과는 다음으로 시작하는 배열의 길이 멤버입니다.${parameter[parameter]}.음의 오프셋은 다음과 비교하여 취합니다.하나가 지정된 배열의 최대 인덱스보다 큽니다.서브 ‐연관 배열에 적용된 문자열 확장은 under를 생성합니다.미세한 결과음의 오프셋은 분리해야 합니다.혼동을 피하기 위해 결장에서 적어도 한 칸.:- 확장을 사용합니다.하위 문자열 인덱싱은 다음을 제외하고 0 기반입니다.위치 매개 변수가 사용됩니다. 이 경우 인덱싱기본적으로 1부터 시작합니다.오프셋이 0인 경우 위치매개 변수가 사용되고 $0이 목록 앞에 붙습니다.
이 순수한 bash 솔루션이 나오지 않은 것이 놀랍습니다.
a="someletters_12345_moreleters.ext"
IFS="_"
set $a
echo $2
# prints 12345
하거나 "IFS를 재설정할 수 있습니다."unset IFS나중에!
Jor의 대답을 기반으로 합니다(나에게는 통하지 않습니다).
substring=$(expr "$filename" : '.*_\([^_]*\)_.*')
요구 사항에 따름
파일 이름에 x자 수를 사용한 다음 양쪽에 하나의 밑줄로 둘러싸인 5자리 시퀀스를 사용하고 다른 x자 수를 사용합니다.저는 5자리 숫자를 가지고 변수에 넣고 싶습니다.
는 약간의 찾요았을 .grep유용한 방법:
$ echo "someletters_12345_moreleters.ext" | grep -Eo "[[:digit:]]+"
12345
또는 그 이상
$ echo "someletters_12345_moreleters.ext" | grep -Eo "[[:digit:]]{5}"
12345
에 그고는으로.-Po구문:
$ echo "someletters_12345_moreleters.ext" | grep -Po '(?<=_)\d+'
12345
또는 정확히 5자로 맞추려는 경우:
$ echo "someletters_12345_moreleters.ext" | grep -Po '(?<=_)\d{5}'
12345
마지막으로 변수에 저장하려면 다음을 사용하면 됩니다.var=$(command)통사론
다음의 개념에 초점을 맞춘다면,
"(한 자리 여러 의 실행""("한자또여러자리연속는"
여러 외부 도구를 사용하여 숫자를 추출할 수 있습니다.
sed 또는 tr 등 다른 모든 문자를 쉽게 지울 수 있었습니다.
name='someletters_12345_moreleters.ext'
echo $name | sed 's/[^0-9]*//g' # 12345
echo $name | tr -c -d 0-9 # 12345
그러나 $name에 여러 런의 숫자가 포함된 경우 위의 항목은 실패합니다.
"name=someletters_12345_moreletters_323_end.ext"인 경우:
echo $name | sed 's/[^0-9]*//g' # 12345323
echo $name | tr -c -d 0-9 # 12345323
정규식을 사용해야 합니다.
에서 첫 번째 실행(323이하려면: sed "perl"을 선택합니다.
echo $name | sed 's/[^0-9]*\([0-9]\{1,\}\).*$/\1/'
perl -e 'my $name='$name';my ($num)=$name=~/(\d+)/;print "$num\n";'
하지만 우리는 그것을 bash에서 직접(1) 할 수 있습니다.
regex=[^0-9]*([0-9]{1,}).*$; \
[[ $name =~ $regex ]] && echo ${BASH_REMATCH[1]}
할 수 .
다른 텍스트/문자로 둘러싸여 있습니다.
참고:regex=[^0-9]*([0-9]{5,5}).*$; :-)는 5자리 런과 일치합니다. :-)
(1)각 짧은 텍스트에 대해 외부 도구를 호출하는 것보다 빠릅니다.대용량 파일의 경우 sed 또는 awk 내부에서 모든 처리를 수행하는 것보다 빠르지 않습니다.
하위 프로세스 없이 다음을 수행할 수 있습니다.
shopt -s extglob
front=${input%%_+([a-zA-Z]).*}
digits=${front##+([a-zA-Z])_}
이것의 아주 작은 변형은 ksh93에서도 작동할 것입니다.
제 대답은 당신이 원하는 것을 더 잘 통제할 수 있을 것입니다.다음은 추출 방법에 대한 코드입니다.12345을
str="someletters_12345_moreleters.ext"
str=${str#*_}
str=${str%_more*}
echo $str
만약 당신이 어떤 문자라도 가지고 있는 것을 추출하고 싶다면 이것이 더 효율적일 것입니다.abc또는 같은 특별한 캐릭터들._또는- 예: 예:, 만당신끈이당렇신고면원그것 뒤에 있는 ,someletters_ 그이에 앞에_moreleters.ext:
str="someletters_123-45-24a&13b-1_moreleters.ext"
내 코드로 당신이 정확히 원하는 것을 말할 수 있습니다.설명:
#*일치하는 키를 포함한 이전 문자열이 제거됩니다.은 여서우가언핵한심은입니다._ %일치하는 키를 포함하여 다음 문자열을 제거합니다.입니다.
직접 몇 가지 실험을 해보면 이것이 흥미롭다는 것을 알게 될 것입니다.
첫 번째 숫자 블록과 일치하고 주변 밑줄에 의존하지 않는 접두사-접미사 솔루션(JB 및 Darron에서 제공한 솔루션과 유사)은 다음과 같습니다.
str='someletters_12345_morele34ters.ext'
s1="${str#"${str%%[[:digit:]]*}"}" # strip off non-digit prefix from str
s2="${s1%%[^[:digit:]]*}" # strip off non-digit suffix from s1
echo "$s2" # 12345
셸 자르기 - 문자열에서 특정 범위의 문자 또는 지정된 부분을 인쇄합니다.
#method1) bash 사용
str=2020-08-08T07:40:00.000Z
echo ${str:11:8}
#method2) 컷 사용
str=2020-08-08T07:40:00.000Z
cut -c12-19 <<< $str
#method3) awk로 작업할 때
str=2020-08-08T07:40:00.000Z
awk '{time=gensub(/.{11}(.{8}).*/,"\\1","g",$1); print time}' <<< $str
나는 사랑한다sed정규식 그룹을 처리하는 기능:
> var="someletters_12345_moreletters.ext"
> digits=$( echo "$var" | sed "s/.*_\([0-9]\+\).*/\1/p" -n )
> echo $digits
12345
조금 더 일반적인 옵션은 밑줄이 있다고 가정하지 않는 것입니다._순서의 합니다. 에 얻은 를 제거합니다.: ▁marking다표니시합시▁you작을▁all. 예를 들어 시퀀스 전에 얻은 모든 비숫자를 제거합니다.s/[^0-9]\+\([0-9]\+\).*/\1/p.
> man sed | grep s/regexp/replacement -A 2
s/regexp/replacement/
Attempt to match regexp against the pattern space. If successful, replace that portion matched with replacement. The replacement may contain the special character & to
refer to that portion of the pattern space which matched, and the special escapes \1 through \9 to refer to the corresponding matching sub-expressions in the regexp.
regexps에 대해 너무 자신이 없는 경우 이에 대한 추가 정보:
s는 _s_substitute_s_s_sutute 파일입니다.[0-9]+1과 합니다.\1정규식 출력의 그룹 n.1에 대한 링크(그룹 0은 전체 일치, 그룹 1은 괄호 안의 일치)p에 대한 것입니다.
이스케이프\만들 곳이 있습니까?sed의 regexp 처리 작업입니다.
주어진 시험.txt는 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"가 포함된 파일입니다.
cut -b19-20 test.txt > test1.txt # This will extract chars 19 & 20 "ST"
while read -r; do;
> x=$REPLY
> done < test1.txt
echo $x
ST
php의 substrabcdefg', 2-1, 3)와 유사함:
echo 'abcdefg'|tail -c +2|head -c 3
이것이 원하는 출력을 얻는 데 도움이 될 수 있습니다.
코드:
your_number=$(echo "someletters_12345_moreleters.ext" | grep -E -o '[0-9]{5}')
echo $your_number
출력:
12345
예, 여기 빈 문자열이 있는 순수 매개 변수 대체가 있습니다.주의할 점은 일부 문자와 더 많은 문자를 문자로만 정의했다는 것입니다.영숫자인 경우에는 그대로 작동하지 않습니다.
filename=someletters_12345_moreletters.ext
substring=${filename//@(+([a-z])_|_+([a-z]).*)}
echo $substring
12345
bash in built in 'expr' 명령도 있습니다.
INPUT="someletters_12345_moreleters.ext"
SUBSTRING=`expr match "$INPUT" '.*_\([[:digit:]]*\)_.*' `
echo $SUBSTRING
배시 솔루션:
IFS="_" read -r x digs x <<<'someletters_12345_moreleters.ext'
라는 변수를 정리할 것입니다.x »x var로 될 수 ._.
input='someletters_12345_moreleters.ext'
IFS="_" read -r _ digs _ <<<"$input"
파이프와 서브셸이 필요한 이 문제에 대한 많은 구식 해결책.bash3(2004년 연산자 bash 3(2004년 출시)이 내장되어 .=~.
input="someletters_12345_moreleters.ext"
# match: underscore followed by 1 or more digits followed by underscore
[[ $input =~ _([0-9]+)_ ]]
echo ${BASH_REMATCH[1]}
출력:
12345
참고로, RegExp의 작성에 능숙하지 않다면 정규 표현식 마스터링을 읽는 것을 추천합니다.
.com 에서 하면 RegExp와 같은 를 얻을 수 .com 에서 온라인 GUI를 시도하고 "Flavor"를 "PCRE"로 설정하면 다음과 같은 POSIX 스타일 문자 클래스를 얻을 수 있습니다.[[:digit:]] 그거bash사용하다.
JS 및 Java 구현과 유사한 잉크루시브 엔드.이것을 원하지 않으면 +1을 제거합니다.
function substring() {
local str="$1" start="${2}" end="${3}"
if [[ "$start" == "" ]]; then start="0"; fi
if [[ "$end" == "" ]]; then end="${#str}"; fi
local length="((${end}-${start}+1))"
echo "${str:${start}:${length}}"
}
예:
substring 01234 0
01234
substring 012345 0
012345
substring 012345 0 0
0
substring 012345 1 1
1
substring 012345 1 2
12
substring 012345 0 1
01
substring 012345 0 2
012
substring 012345 0 3
0123
substring 012345 0 4
01234
substring 012345 0 5
012345
기타 통화 예제:
substring 012345 0
012345
substring 012345 1
12345
substring 012345 2
2345
substring 012345 3
345
substring 012345 4
45
substring 012345 5
5
substring 012345 6
substring 012345 3 5
345
substring 012345 3 4
34
substring 012345 2 4
234
substring 012345 1 3
123
SED 교체를 쉽게 사용할 수 있는 방법:
result=$(echo "someletters_12345_moreleters.ext" | sed 's/.*_\(.*\)_.*/\1/g')
echo $result
조금 늦었지만, 이 문제를 우연히 발견하고 다음을 발견했습니다.
host:/tmp$ asd=someletters_12345_moreleters.ext
host:/tmp$ echo `expr $asd : '.*_\(.*\)_'`
12345
host:/tmp$
날짜에 %N이 없는 임베디드 시스템에서 밀리초 단위의 해상도를 얻기 위해 사용했습니다.
set `grep "now at" /proc/timer_list`
nano=$3
fraction=`expr $nano : '.*\(...\)......'`
$debug nano is $nano, fraction is $fraction
여기 하위 문자열이 있습니다.sh 파일
사용.
`substring.sh $TEXT 2 3` # characters 2-3
`substring.sh $TEXT 2` # characters 2 and after
부현의sh는 이 선을 따릅니다.
#echo "starting substring"
chars=$1
start=$(($2))
end=$3
i=0
o=""
if [[ -z $end ]]; then
end=`echo "$chars " | wc -c`
else
end=$((end))
fi
#echo "length is " $e
a=`echo $chars | sed 's/\(.\)/\1 /g'`
#echo "a is " $a
for c in $a
do
#echo "substring" $i $e $c
if [[ i -lt $start ]]; then
: # DO Nothing
elif [[ i -gt $end ]]; then
break;
else
o="$o$c"
fi
i=$(($i+1))
done
#echo substring returning $o
echo $o
언급URL : https://stackoverflow.com/questions/428109/extract-substring-in-bash
'programing' 카테고리의 다른 글
| SQL Server에서 주의 첫 번째 요일 가져오기 (0) | 2023.05.25 |
|---|---|
| MongoDB 및 Nodejs를 사용한 날짜 삽입 및 쿼리 (0) | 2023.05.25 |
| 다른 지점으로 전환하려면 어떻게 해야 합니까? (0) | 2023.05.25 |
| C++ 표준::쌍의 C# 아날로그는 무엇입니까? (0) | 2023.05.25 |
| .NET 표준과 .NET 코어 비교 (0) | 2023.05.25 |

