문자열 s가 주어지면
s="B /home/BL/004_010_0100.0 23 0.031"
문자열에서 경로, 탭 및 공백 뒤의 숫자만 파악하는 방법은 무엇입니까?
위의 문자열 s에서 숫자 23을 추출하고 싶습니다.
num=$(echo $s | grep 'B .*\t (\d*)')
답변1
문자열을 공백으로 구분된 필드 집합으로 처리합니다. 마지막에서 두 번째 필드가 필요합니다.
num=$( awk '{ print $(NF-1) }' <<<"$s" )
아니면 여기 문자열이 없는 쉘에서,
num=$( printf '%s\n' "$s" | awk '{ print $(NF-1) }' )
그러면 명령 $s
에 문자열이 입력됩니다 . awk
이 awk
명령은 공백으로 구분된 마지막 필드에서 두 번째 필드를 출력합니다. 결과는 num
변수에 할당됩니다.
시험:
$ s="B /home/BL/004_010_0100.0 23 0.031"
$ num=$( awk '{ print $(NF-1) }' <<<"$s" )
$ printf 'num is "%s"\n' "$num"
num is "23"
데이터가 $s
명령 에서 나온 경우 awk
중간 변수에 저장하는 대신 직접 입력할 수 있습니다.
num=$( some-command | awk '{ print $(NF-1) }' )
grep
일치하는 항목을 반환하는 도구입니다.철사-o
(이 도구의 일부 구현에서 사용할 수 있는 비표준 옵션은 무시하십시오.) 먼저 문자열의 공백을 기준으로 문자열을 여러 줄로 변환하면 이를 사용하여 grep
숫자를 선택할 수 있습니다.$s
$ tr -s '[:blank:]' '[\n*]' <<<"$s" | grep -x '[[:digit:]]\{1,\}'
23
여기에 사용된 명령은 tr
문자열을 다음에서 변환합니다.
B /home/BL/004_010_0100.0 23 0.031
입력하다
B
/home/BL/004_010_0100.0
23
0.031
grep
명령이 이 줄을 선택했습니다 .오직숫자로 구성됩니다(이 -x
옵션은 주어진 패턴이 완전한 행과 일치하도록 강제합니다). 분명히 이것은 찾고 있는 숫자가 양의 정수인 경우에만 작동합니다.
두 번째 "필드"에 관심이 있다는 것을 알고 있다면 대신 다음을 사용할 수 tail
있습니다 head
.
$ tr -s '[:blank:]' '[\n*]' <<<"$s" | tail -n 2 | head -n 1
23
... 또는 sed
:
$ tr -s '[:blank:]' '[\n*]' <<<"$s" | sed -n -e '${ g; p; }' -e h
23
위의 모든 변형은 표준이며 이식 가능합니다. 비표준 유틸리티를 사용하여 줄을 두 번 뒤집 cut
으면 끝에서 두 번째 필드를 추출하는 데 사용할 수도 있습니다.rev
$ rev <<<"$s" | tr -s '[:blank:]' '[\t*]' | cut -f 2 | rev
23
여기서는 tr
모든 공백 문자를 대체하기 위해 탭을 사용합니다(그리고 이를 다음과 같이 압축합니다).하나의탭). cut
그런 다음 두 번째 필드를 추출하고 rev
추출된 데이터를 다시 반전하면 됩니다.
답변2
Perl로 이것을 시도해 볼 수 있습니다:
echo "$s" | perl -e 'for(<>){/B\s+.*?\s+(\d+)\s+/;print $1}'
여기서는 다음과 같은 문자열을 찾습니다.
B
특징- 그 뒤에 하나 이상의 공백 문자가 옵니다.
\s+
- 첫 번째 공백 문자 앞에 모든 게으른 문자가 옵니다.
.*?\s+
- 다음은 우리가 원하는 숫자입니다. 괄호 안의 캡처 그룹에 캡처하여 특수 변수
(\d+)
에 저장됩니다.$1
- 그 뒤에는 하나 이상의 공백 문자가 옵니다 -
\s+
.
이 정규식은 개선될 수 있습니다(예: ^
및 $
연산자를 사용하여 문자열의 시작과 끝을 나타냄).
더 읽어보세요정규 표현식에 대해.
답변3
GNU grep
(Linux 시스템의 기본값)에 액세스할 수 있는 경우 이 정규 표현식은 소수점 이하 자릿수 없이 숫자를 캡처합니다.
grep -oP '\b(?<!\.)\d+(?!\.)\b'
정규식 설명:
\b
단어 경계 일치(?<!\.)
.
Negative Lookbehind는 ( ) 뒤에 소수점이 없다고 주장합니다 .\d+
숫자가 한 번 이상 일치합니다.(?!\.)
Negative Lookahead는 앞에 소수점이 없다고 주장합니다(.
).\b
단어 경계 일치
답변4
grep
조금 바뀌었을 뿐입니다 . GNU grep
(Linux 시스템의 기본값) 를 사용하는 경우 다음과 같이 작동합니다.
s="B /home/BL/004_010_0100.0 23 0.031"
num=$(echo $s | grep -oP '\.*?\s+\d+\s+')