Linux와 Mac 간에 크로스 플랫폼/표준 sed를 사용하는 방법은 무엇입니까?

Linux와 Mac 간에 크로스 플랫폼/표준 sed를 사용하는 방법은 무엇입니까?

안녕하세요, 프로젝트 배포를 위해 makefile에서 실행하는 스크립트가 있습니다. 여기에서는 sed를 사용하여 입력 문자열에서 환경과 프로젝트 이름을 캡처하고 있으며 우분투에서 훌륭하게 작동합니다.

이 간단한 명령

 echo deploy-api-production | sed -E 's/deploy-\w+-(\w+)/\1/'

production우분투에서 예상 결과를 제공합니다

우분투 실행

$  echo deploy-api-production | sed -E 's/deploy-\w+-(\w+)/\1/'
production

하지만 Mac에서는 전체 문자열을 제공합니다.deploy-api-production

맥 실행:

$  echo deploy-api-production | sed -E 's/deploy-\w+-(\w+)/\1/'
deploy-api-production

Mac에서 동일한 결과를 얻을 수 있도록 일종의 통합 sed가 있습니까?

출력이 Mac 실행의 결과물이기를 원합니다.

사례 2 - 보다 일반적이며 접두사도 포함됩니다.

이것을 올바르게 분석하고 싶습니다

echo a-deploy-api-production | someprocessing
production

so는 위의 상황과 유사하지만 a-단어 앞에 추가 접두어 단어가 있습니다.deploy

현재 주어진 솔루션과 비슷한 것을 시도했지만 성공하지 못했습니다.

echo a-deploy-api-production | awk -F'-' '$1=="a-deploy"{print $3}'

위의 결과는 비어 있습니다. 결과를 얻기 위해 수정하고 싶습니다.production

답변1

당신은 그것을 사용할 수 있습니다 awk:

echo deploy-api-production | awk -F'-' '$1=="deploy"{print $3}'

이렇게 하면 텍스트가 로 구분된 부분으로 분할됩니다 -. 첫 번째 필드가 단어와 일치해야 deploy하고 세 번째 필드가 인쇄됩니다.

업데이트된 질문에 새로운 변형이 포함되었습니다. 동일한 코드를 사용하여 awk직접 비교할 수는 없습니다. a-deploy이는 두 개의 필드(대시로 구분됨)와 $1첫 번째 필드(즉, 이 새 인스턴스에는 a없음 )만 있기 때문입니다.deploy

deploy모든 사용 사례를 알지 못한 채 문자열의 아무 곳이나 검색하고 발견되면 마지막 필드를 인쇄하는 것이 더 좋을 것이라고 제안합니다 . (이것은 원래 케이스에도 적용됩니다.)

echo deploy-api-production | awk -F'-' '/deploy/ {print $NF}'
production

echo a-deploy-api-production | awk -F'-' '/deploy/ {print $NF}'
production

답변2

POSIX 사용-라이 sed, 두 시나리오 모두 그림과 같이 원하는 결과를 얻을 수 있습니다.

w='[[:alpha:]][_[:alnum:]]*'
echo 'deploy-api-productionN' | 
sed -n -e "/^\($w-\)\{0,1\}deploy-/s/^$w\(-\($w\)\)\{1,\}\$/\2/p"

관찰 결과:

  • sed에는 단어에 대한 기호가 없으므로 이에 대한 정규식을 작성하고 이를 쉘 변수에 저장합니다.$w
  • \{0,1\}은 BRE인가요?
  • \{1,\}은 +의 BRE입니다.
  • \(...\)는 (...)의 BRE입니다.

답변3

GNU 시스템은 PCRE(Perl 호환 정규식). 이러한 기호(예: \s\w)는 표준 기호가 아니며 sed모든 시스템(일반적으로 GNU 시스템 외부)에서 지원되지 않습니다.

-줄이 하위 문자열 또는 로 시작하는 경우 deploy마지막 줄(대시) 뒤에 줄의 마지막 부분을 출력하려는 ​​것 같습니다 something-deploy.

표준 방법을 사용하여 sed이 작업을 수행할 수 있습니다.

sed '/^deploy/ s/.*-//'

또는

sed '/^something-deploy/ s/.*-//'

이러한 표현식은 이전 정규 표현식이 현재 입력 행과 일치하는 경우 sed대체를 트리거합니다 . s/.*-//이 교체는 마지막 대시를 포함하여 줄의 모든 것을 제거합니다.

이 경우 필요한 경우 트리거 표현식을 대체 표현식과 결합할 수 있습니다.

sed 's/^deploy.*-//'
sed 's/^something-deploy.*-//'

데이터가 (질문에서와 같이) 정적 문자열 출력이 아니고 echo변수의 일부 값인 경우 외부 프로그램을 호출하는 것보다 쉘에서 이 작업을 수행하는 것이 더 효율적입니다.

string=deploy-api-production

if [[ $string == deploy-* ]]; then
    printf '%s\n' "${string##*-}"
fi

printf에 표시된 대로 수정된 값을 유지하려면 대신 변수 할당을 사용합니다 new=${string##*-}.

확장은 쉘 패턴과 일치하는 ${variable##pattern}가장 긴 접두사 문자열에서 제거됩니다 .$variablepattern

관련 정보