Korn Shell의 각 요소에 정규식을 적용하여 문자열 배열을 반복합니다.

Korn Shell의 각 요소에 정규식을 적용하여 문자열 배열을 반복합니다.

names이름과 일부 후속 정크 데이터가 포함된 문자열 배열이 있습니다 . 이와 같이

Jill Shortz, City Contractor, America
Bill Torts, Family Doctor, Canada
Will Courtz, Folk DJ, Bulgaria
Phil-Lip Warts, Juggler, India

names정규식을 사용하여 처음 두 단어만 추출 (^\w+-*( *\w+)*)하고 다시 작성하여 names다음을 포함하도록 반복하고 싶습니다.

Jill Shortz
Bill Torts
Will Courtz
Phil-Lip Warts

이것이 내가 시도한 것이지만 내 AIX 시스템은 -PPerl 모드에서 실행할 때 매개변수를 좋아하지 않습니다.

for((i=0;i<${#names[@]};++i)); do
        names[$i]=`grep -P '(^\w+-*( *\w+)*)' -o <<<"${names[i]}"`
done

답변1

나는 첫 번째 쉼표 뒤의 모든 항목을 제거하기를 원한다고 가정할 때 정규식이 이 작업에 유용하다고 생각하지 않습니다.

names=( "${names[@]%%,*}" )
printf '"%s"\n' "${names[@]}"

이렇게 하면 각 배열 요소에서 첫 번째 쉼표와 그 뒤의 모든 항목(문자 그대로 "와일드카드 패턴과 일치하는 가장 긴 접미사 ,*")이 개별적으로 제거됩니다. 그런 다음 수정된 이름의 결과 목록이 배열에 다시 할당되고 names인쇄 됩니다 printf.

질문과 같은 목록으로 배열을 초기화한다는 점을 고려하면 이 코드는 다음을 생성합니다.

"Jill Shortz"
"Bill Torts"
"Will Courtz"
"Phil-Lip Warts"

(큰따옴표는 printf형식 문자열에 의해 추가됩니다).

이 코드는 , ksh93및 에서 작동합니다 .bashzshyash

답변2

ksh 매뉴얼 페이지 어디에도 문자열을 정규식과 일치시키고 캡처 괄호를 사용하여 하위 문자열을 추출할 수 있는 곳이 없습니다(bash에서와 같이

[[ $str =~ ^([[:alnum:]]+([ -]+[[:alnum:]]+)+) ]] && echo "${BASH_REMATCH[1]}"

그러나 glob 패턴에서 확장 정규식을 사용할 수 있으므로 ~(E:regex)다음을 수행할 수 있습니다.

for n in "${names[@]}"; do
  # remove the pattern from the start of the string
  tmp=${n##~(E:\w+([ -]+\w+)*)}
  # and then remove what remained from the end of the string
  echo "[${n%$tmp}]"
done
[Jill Shortz]
[Bill Torts]
[Will Courtz]
[Phil-Lip Warts]

...그리고 최대 쓰기 전용 읽기 불가능성

for n in "${names[@]}"; do
  echo "${n%${n##~(E:\w+([ -]+\w+)*)}}"
done

관련 정보