줄 구분 기호 사이의 정확한 문자 집합을 변경하는 방법은 무엇입니까?

줄 구분 기호 사이의 정확한 문자 집합을 변경하는 방법은 무엇입니까?

dovecot 사용자 데이터베이스에서 사용자 비밀번호를 변경하는 스크립트를 작성하려고 하는데 sed.

예를 들어 다음 줄을 확인하세요(이것은 dovecot userdb의 일부입니다).

[email protected]:{SHA512-CRYPT}$6$0vthg.LubtSCxRRK$MdTKNQ2Vk8ZW3XQXNXStt9rfr6fNa‌​XqPvZ0o9WJ8mW8y9ozE1pi8dYM8oQzwWa8ESGzEmJO6yT/tgi3ZEqAiE0:::
[email protected]:{SHA512-CRYPT}$6$0vthg.LubtSCxRRK$MdTKNQ2Vk8ZW3XQXNXStt9rfr6fNa‌​XqPvZ0o9WJ8mW8y9ozE1pi8dYM8oQzwWa8ESGzEmJO6yT/tgi3ZEqAiE0:::

사용자에 대해서만 "{SHA512-CRYPT}"로 시작하는 ":" 구분 기호 사이의 문자열을 바꾸는 방법[이메일 보호됨]"사용자에게는 적용되지 않습니다"[이메일 보호됨]"sed를 사용하시나요?

답변1

아마도:

sed 's/\(\(^\|:\)123@example\.com:\)\([^:]\+\)/\1foo/'

값에 이스케이프된 구분 기호가 없다고 가정합니다.

sed 's/\(\(^\|:\)123@example\.com:\)\([^:]\+\)/\1foo/'    
     |     |         |                |     | |  | |     
     |     |         |                |     | |  | +----- H. End of sub.
     |     |         |                |     | |  +------- G. Sub string
     |     |         |                |     | +---------- F. Match Group 1.
     |     |         |                |     +------------ E. End of Group 3.
     |     |         |                +------------------ D. Group 3.
     |     |         +----------------------------------- C. User
     |     +--------------------------------------------- B. Prefix Group 2.
     +--------------------------------------------------- A. Substitute
  • A: s/대체 명령.
  • B: (^|:)행 또는 구분 기호의 시작 부분에서 시작하는 :그룹 2는 그룹 1의 일부와 일치합니다.
  • C:매칭 대상 사용자는 매칭 그룹 1에 속해 있습니다.
  • D: ([^:]+)삭제할 부분까지 모두 가능합니다 :. 그룹 3의 일부입니다. 다음 구분 기호까지의 모든 것입니다. 어쩌면 그래야 할지도 \(:\|$\)모르지만, 그것으로 끝날 것이기 때문에 :충분할 것입니다.
  • E: \)그룹 제거를 종료합니다.
  • F: \1일치하는 그룹 1을 다시 놓습니다. 사용자+구분자.
  • G: foo모든 것이 지하실에 삽입됩니다.
  • H: /모두 끝내세요. 선택적으로 /g전역이지만 한 번만 발생한다고 가정합니다.

답변2

여기에서 주소를 바꿀 수 있습니다.

sed '/^[email protected]:{SHA512-CRYPT}/s/{[^:]*/REPLACE/'

여기서 s///대체 명령은 address 의 함수이므로 /regxp/s///이 먼저 상위 주소와 일치하지 않는 한 대체가 시도되지 않습니다.

아니면 그냥 s///:

sed 's/^\([email protected]:\){SHA512-CRYPT}[^:]*/\1REPLACE/'

또는 123이 콜론 바로 뒤에 나오지 않는 경우에만 줄의 시작 부분에 고정합니다.

sed 's/^\(\(.*:\)*[email protected]:\){SHA512-CRYPT}[^:]*/\1REPLACE/'

나는 확실히 복잡한 하위 표현식에 대해 낯설지 않지만, 이 경우에는 그런 것이 불필요합니다. 나는 일반적으로 주소 형식을 얻을 수 있을 때 선호합니다. 읽기 쉽고, 더 효율적이며, 완전히 이식 가능하다고 생각합니다. 하지만 언뜻 보면 제가 처음에는 여기에 내재된 복잡성을 과대평가한 것처럼 보였습니다.

마찬가지로 역참조와 실제 교체를 분리할 수 있습니다. 예를 들면 다음과 같습니다.

sed -e '
/^\([email protected]:\){SHA512-CRYPT}[^:]*/!b
s//\1REPLACE/
#other commands that can be sure to affect only a line matching the 1st address'

위의 예에서 address는 b일치하지 않는 줄을 스크립트에서 제거하여 일치를 확인하지만, !줄이 일치 테스트를 통과하면 다음 대체를 위해 변수 비트를 저장하는 이중 임무도 수행합니다. 게다가 모든 후속 명령은 시작 주소와 일치하는 라인에서만 실행될 수 있습니다.\1s///

물론 중괄호를 사용하여 일치하는 함수 컨텍스트를 지정하는 덜 궁극적인 형식도 있습니다.

sed -e '
/^[email protected]:{SHA512-CRYPT}/{
    s/{[^:]*/REPLACE/
    #other function commands
};/other match function/{
    #still more commands...
}'

답변3

사용 awk:

awk -F':' '/^[email protected]/ {$2="NEWPASSWORDHERE"}1' OFS=':' infile

[email protected]:NEWPASSWORDHERE:::
[email protected]:{SHA512-CRYPT}$6$0vthg.LubtSCxRRK$MdTKNQ2Vk8ZW3XQXNXStt9rfr6fNa‌​XqPvZ0o9WJ8mW8y9ozE1pi8dYM8oQzwWa8ESGzEmJO6yT/tgi3ZEqAiE0:::
  • awk해당 옵션을 사용하여 콜론()을 필드 구분자로 -F설정 하고 행이 시작되면() 열2를 새 값()으로 바꿉니다 .:^[email protected]$2NEWPASSWODHERE

  • OFS=':'출력 필드 구분 기호를 공백(기본값)에서 콜론( :)으로 변경합니다.

  • 마지막으로 1인쇄는 기본적으로 활성화됩니다.

관련 정보