HOWTO · Bash

Bash에서 부분 문자열 추출

이 자습서에서는 cut 명령, 부분 문자열 확장 및 내부 필드 구분 기호를 사용하여 bash에서 부분 문자열을 추출하는 다양한 방법을 보여줍니다.

이 페이지의 내용

Bash에서 문자열의 일부를 얻으려면 입력에 맞는 작업을 선택하세요. cut는 구분자로 나뉜 필드를 선택하고, Bash 부분 문자열 확장은 위치를 기준으로 문자를 선택하며, IFS 분할은 구분된 텍스트를 따로 처리할 수 있는 필드로 나눕니다. 이 방법들은 서로 관련되어 있지만 결과를 반환하는 방식은 서로 다릅니다.

구분된 필드를 cut로 추출하기

값에 일관된 구분자가 있고 특정 필드를 가져오려면 cut를 사용하세요. -d 옵션은 구분자를 지정하고, -f 옵션은 1부터 세는 필드 번호를 선택합니다. 이 예제에서는 밑줄로 단어를 구분하므로 세 번째 필드는 three입니다. 변수 확장을 따옴표로 감싸 printf에 전달하면 값이 하나의 입력 줄로 유지되고, 안전하지 않은 echo $numbers처럼 따옴표 없이 쓰는 형식을 피할 수 있습니다.

다음 예제를 실행하세요:

이 섹션의 코드와 표시되는 레이블 또는 출력은 영어로 유지됩니다.

numbers='one_two_three_four_five'
substring=$(printf '%s\n' "$numbers" | cut -d '_' -f 3)
printf 'substring: %s\n' "$substring"
substring: three

cut는 필드를 선택하며 임의의 문자 범위를 추출하지는 않습니다. 구분자와 필드 위치가 정해진 구조화된 텍스트에 적합합니다. 원하는 범위를 위치로 지정하려면 부분 문자열 확장을 사용하세요.

Bash 부분 문자열 확장으로 문자 추출하기

Bash는 ${variable:offset:length} 형식으로 부분 문자열을 확장합니다. 오프셋은 0부터 시작하며, 길이는 반환할 문자 수입니다. 예를 들어 one_two_three_four_five에서 오프셋 4는 two의 t부터 시작하고, 길이 3은 해당 문자 세 개를 선택합니다. 구분자를 포함해 원래 문자열의 모든 문자가 오프셋 계산에 포함됩니다.

다음 예제를 실행하세요:

이 섹션의 코드와 표시되는 레이블 또는 출력은 영어로 유지됩니다.

numbers='one_two_three_four_five'
substring=${numbers:4:3}
printf 'substring: %s\n' "$substring"
substring: two

문자의 위치와 범위를 알고 있을 때 바로 선택할 수 있는 방법입니다. 오프셋은 필드 번호가 아닙니다. 원하는 부분 앞의 텍스트 길이가 바뀌면 같은 오프셋으로 다른 문자가 선택될 수 있습니다. 값이 이름이 붙은 필드나 번호가 매겨진 필드로 구분되어 있다면 cut 또는 IFS를 사용하는 편이 보통 더 쉽게 조정할 수 있습니다.

IFS로 문자열을 필드로 나누기

IFS는 Bash의 내부 필드 구분자입니다. 따옴표로 감싸지 않은 확장 뒤에 수행되는 단어 분할을 제어하며, read 내장 명령이 입력을 나누는 방식에도 영향을 줍니다. IFS 값을 일시적으로 설정하면 구분된 문자열을 위치 매개변수로 나눌 수 있습니다. $1, $2, $3은 각각 첫째, 둘째, 셋째 매개변수를 가리키며 배열 인덱스 문법이 아닙니다.

이 예제는 분할을 함수 범위 안에서 수행하고, 따옴표 없는 확장을 사용하기 전에 경로명 확장을 비활성화합니다. 단어 분할 다음에 경로명 확장이 실행되기 때문에 이 설정이 중요합니다. 필드에 *, ? 또는 대괄호 패턴이 들어 있으면 셸이 이를 일치하는 파일 이름으로 바꿀 수 있습니다. 구분자가 정해진 제어된 입력에는 이 형식을 사용하세요. 구분자가 공백이 아니라면 입력을 read -a로 배열에 읽어 들일 때 IFS를 해당 구분자로 설정한 뒤, 필드를 사용할 때 배열 확장을 따옴표로 감싸세요. 기본 IFS에서는 공백, 탭, 줄 바꿈으로 필드가 나뉩니다. IFS를 구분자로 바꾸면 입력이 해당 문자에서 나뉩니다. 이 방법은 선택한 구분자가 필드 안에 포함된 경우 이를 보존하지 못하며, 줄 단위로 읽는 read -a는 필드 안의 줄 바꿈도 보존할 수 없습니다. 그런 형식에는 read -a만 사용하지 말고 해당 형식에 맞는 파서를 사용하세요.

다음 예제를 실행하세요:

이 섹션의 코드와 표시되는 레이블 또는 출력은 영어로 유지됩니다.

numbers='one_two_three_four_five'
extract_second() (
  local IFS=_
  set -f
  set -- $numbers
  printf 'second field: %s\n' "$2"
)
extract_second
second field: two

함수 안에서 set --은 함수의 위치 매개변수를 분할된 필드로 바꿉니다. 함수가 끝나면 호출자의 위치 매개변수가 복원됩니다. 지역 구분자 설정은 스크립트의 IFS를 영구적으로 바꾸지 않습니다.

적합한 방법 선택하기

구분자가 정해진 텍스트에서 밑줄로 구분된 세 번째 값처럼 번호가 매겨진 필드를 선택하려면 cut를 사용하세요. 0부터 세는 오프셋과 길이로 위치가 정해진 문자를 가져오려면 Bash 부분 문자열 확장을 사용하세요. 필드를 별도의 셸 단어 또는 위치 매개변수로 만들어 추가 처리하려면 IFS 분할을 선택하세요.

입력이 예측 가능하다면 각 방법은 간결합니다. cut에 전달하는 입력은 따옴표로 감싸고, 부분 문자열 확장에는 중괄호를 사용하세요. IFS 분할을 위해 확장을 따옴표 없이 쓰면 경로명 확장도 일어날 수 있다는 점을 기억하세요. 구분자가 데이터의 일부이거나 필드에 셸 패턴 문자가 들어갈 수 있다면, 따옴표로 감싼 배열 요소로 필드를 보존하는 파싱 방식을 사용하고 따옴표 없는 단어 분할에만 의존하지 마세요. 이렇게 구분하면 필드 번호, 문자 오프셋, 위치 매개변수를 서로 바꿔 쓸 수 있는 “부분 문자열” 표현으로 혼동하지 않을 수 있습니다.