문자열의 경로, 탭 및 공백 뒤의 grep 숫자

문자열의 경로, 탭 및 공백 뒤의 grep 숫자

문자열 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에 문자열이 입력됩니다 . awkawk명령은 공백으로 구분된 마지막 필드에서 두 번째 필드를 출력합니다. 결과는 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+')

관련 정보