예를 들어, 다음은 md5sum 명령의 출력입니다.
35c9581c469c366e286be708a9d9f939 input.txt
이것은 내가 실행 중인 명령줄입니다.
md5sum input.txt | sed -f script.sed
md5sum의 출력이 다음과 같기를 원합니다.
35c9xxxxxxxxxxxxxxxxxxxxxxxxxxxx input.txt
현재 내 .sed 스크립트에는 처음 4자를 제외한 모든 내용을 편집하는 다음 내용이 포함되어 있습니다.
s/./x/5g
공백 "" 을 발견하면 이 작업을 중지해야 합니다 . 어떤 아이디어가 있나요?
답변1
if (md5sum) hash; 그러면 이 작업이 수행됩니다(중괄호 확장을 지원하는 쉘에서).
sed -e's/./x/'{5..32} infile
else 첫 번째 문자 공백이 표시될 때까지 모든 문자 길이에 대해 다음을 수행합니다.
sed
일반 솔루션으로 , 및 를 사용하십시오 .
sed -E ':a s/^(.{4}x{0,})[^x ]/\1x/;ta' infile
:a
는sed우리의 이름이 붙은 태그a
s/
아래 일치 항목을 교체하세요.^
행 앵커 포인트의 시작입니다.(
조별 예선 시작.
단일 문자 일치.{4}
4개 문자(또는....
)만 일치하고 뒤에 오는 문자와 일치합니다.x{0,}
0자 이상x
(또는x*
)
)
그룹 매치가 종료되고 역방향 참조는\1
[^x ]
strings 를 제외한 모든 문자와 일치합니다x
.(문자 클래스에서 해당
^
문자가 열린 직후 첫 번째 문자인 경우 부정 일치가 이루어집니다.)[
[^...]
/
아래와 함께\1
는 위에서 일치하는 부분에 대한 역참조(...)
이므로 첫 번째 부분이 다시 제자리에 있지만x
나중에 추가 콘텐츠가 추가됩니다.- 그리고 하나 , 위에서 우리가 조별 예선에서 득점
x
하지 못했다는 사실을 기억하시나요 ? 이제 하나씩 교체할 캐릭터들 입니다 .[^x ]
(...)
x
/
교체 종료;
새 명령 시작ta
a
교체가 성공하면 레이블로 이동합니다. 그렇지 않으면 모든 문자를 다음으로 교체했으며 이제 교체하고 명령을x
종료할 문자가 남아 있지 않음을 의미합니다.sed
답변2
md5sum
해시에 대해 항상 32자의 출력을 생성합니다. 공백을 검색하는 대신 32자를 찾은 다음 공백을 찾은 다음 마지막 28자를 X로 바꿀 수 있습니다.
md5sum input.txt | sed -E 's/^([[:xdigit:]]{4})[[:xdigit:]]{28} /\1xxxxxxxxxxxxxxxxxxxxxxxxxxxx /'
35c9xxxxxxxxxxxxxxxxxxxxxxxxxxxx input.txt
분해 설명:
's/^([[:xdigit:]]{4})[[:xdigit:]]{28} /\1xxxxxxxxxxxxxxxxxxxxxxxxxxxx /'
's/A / B /'
we're substituting patterns matching A with B
's/ [[:xdigit:]] [[:xdigit:]] / /'
we're looking for two groups of hexadecimal characters
's/ [[:xdigit:]]{4} [[:xdigit:]]{28} / /'
The first group has exactly four characters
The second group has exactly twenty-eight characters
's/ ([[:xdigit:]]{4})[[:xdigit:]]{28} / /'
The first group is a "capture group" which we can reference later
's/ ([[:xdigit:]]{4})[[:xdigit:]]{28} /\1 /'
We will print out the first group verbatim in the output
's/ ([[:xdigit:]]{4})[[:xdigit:]]{28} /\1xxxxxxxxxxxxxxxxxxxxxxxxxxxx /'
We will print x's followed by a space for the next 28 characters
's/^([[:xdigit:]]{4})[[:xdigit:]]{28} /\1xxxxxxxxxxxxxxxxxxxxxxxxxxxx /'
The statement must appear at the start of a line and have a space at the end.
답변3
펄 방법:
$ md5sum file | perl -ple 's/^(.{4})(\S+)(\s+.*)/$1 . "x" x length($2) . $3/e'
9191xxxxxxxxxxxxxxxxxxxxxxxxxxxx file
처음 4개 문자( ^(.{4})
)를 찾은 다음 공백이 아닌 문자를 가능한 한 많이( (\S+)
), 첫 번째 이상의 공백을 찾은 다음 줄 끝까지 모든 항목( (\s+.*)
)을 찾습니다. 그런 다음 첫 번째 캡처된 값( $1
, 처음 4자) 으로 대체되고 , 이는 x
두 번째 캡처된 그룹( )의 길이만큼 반복되고 "x" x length($2)
, 마지막 캡처된 그룹이 이어집니다 $3
. /e
를 계산하려면 연산자 끝에 대체가 필요합니다 s///
.
md5sum
물론, 항상 실행되므로 해시 길이(4)가 항상 28이 된다는 것을 안다면 다음과 같이 단순화할 수 있습니다.
$ md5sum file | perl -ple 's/^(.{4})(\S+)/$1 . "x" x 28/e'
9191xxxxxxxxxxxxxxxxxxxxxxxxxxxx file
심지어:
$ md5sum file | perl -ple 's/(?<=.{4})(\S+)/"x" x 28/e'
9191xxxxxxxxxxxxxxxxxxxxxxxxxxxx file
답변4
$ md5sum somefile
d68610fdffd770de94818268899d6abb somefile
$ md5sum somefile | { read -r hash pathname; printf '%.4sxxxxxxxxxxxxxxxxxxxxxxxxxxxx %s\n' "$hash" "$pathname" }
d686xxxxxxxxxxxxxxxxxxxxxxxxxxxx somefile
이는 해시와 경로 이름을 두 개의 쉘 변수로 읽은 다음 이를 인쇄하여 해시의 마지막 28자를 대체합니다 x
.
여러 파일을 지원하려면 루프를 사용하세요.
$ md5sum somefile* | while read -r hash pathname; do printf '%.4sxxxxxxxxxxxxxxxxxxxxxxxxxxxx %s\n' "$hash" "$pathname"; done
d41dxxxxxxxxxxxxxxxxxxxxxxxxxxxx somefile
d686xxxxxxxxxxxxxxxxxxxxxxxxxxxx somefile1
d41dxxxxxxxxxxxxxxxxxxxxxxxxxxxx somefile2