sed 문자열에 잘못된 문자가 포함되어 있습니다

sed 문자열에 잘못된 문자가 포함되어 있습니다

다음과 같은 보기 흉한 문자가 포함된 임의의 문자열이 있습니다.

이 캐릭터는 제거되어야 합니다. 화이트리스트에는 a-zA-Z0-9 -_* + ß ä ü ö () % @ € & =가 포함됩니다. 그리고 공간

이 작업을 수행하는 첫 번째 스크립트는 다음과 같습니다.

regex="[^\-\_\*\+\ß\ä\ö\ü\(\)\%\@\€\&\=\.a-z0-9A-Z\ ]"
replaceChar="_"
echo "testflŒÆ˘ˆı››◊‹ıÓÌˇˆÁÓˆfl̈™ˇÏˆıÍÓÌıÓWÌtest" |sed -e "s/${regex}/${replaceChar}/g"

그러나 이것은 내 결과입니다.

test_ŒÆ__ı____ıÓÌ__ÁÓ__Ì___Ï_ıÍÓÌıÓWÌtest

내 $LANG 출력

LANG=de_DE.UTF-8

echo "testflŒÆ˘ˆı››◊‹ıÓÌˇˆÁÓˆfl̈™ˇÏˆıÍÓÌıÓWÌtest" | od -c
0000000   t   e   s   t 357 254 202 305 222 303 206 313 230 313 206 304
0000020 261 342 200 272 342 200 272 342 227 212 342 200 271 304 261 303
0000040 223 303 214 313 207 313 206 303 201 303 223 313 206 357 254 202
0000060 303 214 313 206 342 204 242 313 207 303 217 313 206 304 261 303
0000100 215 303 223 303 214 304 261 303 223   W 303 214   t   e   s   t
0000120  \n
0000121

답변1

그러면 올바른 정규 표현식이 생성됩니다.

a="$(printf '%s' {a..z} {A..Z} {0..9} - )"
b="_*+ßäöü()%@€&=."

regex="[^$b$a]"
replaceChar="_"

그러면 다음과 같이 작동합니다.

line="testflŒÆ˘ˆı››◊‹ıÓÌˇˆÁÓˆfl̈™ˇÏˆıÍÓÌıÓWÌtest"
echo "$line" | sed -e "s/${regex}/${replaceChar}/g"

test_______________________________W_test

흥미로운 점은 LANG=C명령이 실패하는 경우입니다. 다음과 같은 간단한 정규 표현식을 사용하더라도:

$ (LANG=C; echo "testflŒÆtest" | sed -e "s/[^tesæ]/_/g")
test_____�_test

기호가 무엇인지 확인하려면:

$ (LANG=C; echo "testflŒÆtest" | sed -e "s/[^tesæ]/_/g")|od -An -tcx1
   t   e   s   t   _   _   _   _   _ 303   _   t   e   s   t  \n
  74  65  73  74  5f  5f  5f  5f  5f  c3  5f  74  65  73  74  0a

즉, 303입니다. 더 긴 문자열에 대해서도 반복됩니다. 어쩌면 그것이 당신이 보고 있는 것일 수도 있습니다.

답변2

컬렉션을 잘 이해하지 못하는 경우(또는 그 보완물), 나는 일반적으로 부정, 특히 범위를 믿지 않습니다. 나는 당신의 추악한 문자열에 있는 대부분의 문자를 알지 못하며, 그것이 어디서 왔는지, 또는 내 컴퓨터가 관심을 갖는지 여부도 모릅니다. 나는 다른 문자 중 일부를 인식하고 무엇이든 제거하는 방법을 알고 있지만 모든 추악한 문자가 최소한 유효한 문자인 한.

alnum=0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
sed -e's|.|&\n|g'     -e'# this opens up the string' \
    -e"s|\([-$alnum*_+ßäüö ()%&@=.$€]\)\{0,1\}.\{0,1\}\n|\1_|g" \
<<""
testflŒÆ˘ˆı››◊‹ıÓÌˇˆÁÓˆfl̈™ˇÏˆıÍÓÌıÓWÌtest

testWtest

^ 그렇죠?

따라서 문자열을 \n문자당 한 줄로 분할한 다음 왼쪽에서 오른쪽으로 한 번에 한 문자씩 스캔합니다. 이 작업을 수행할 때 각 문자에 대해 두 가지 작업 중 하나를 수행합니다. 즉, 화이트리스트에 있는 문자 중 하나를 해당 문자의 0~1개 항목으로 바꾸거나 다른 문자의 0~1개 항목을 제거합니다. 두 경우 모두 후행 개행 문자도 제거됩니다.

밑줄을 사용하면 무엇을 하는지 더 쉽게 알 수 있을 것 같습니다 _.(아마도 그래서 포함시켰을 겁니다):

sed -e's|.|&\n|g'     -e'# this opens up the string' \
    -e"s|\([-$alnum*_+ßäüö ()%&@=.$€]\)\{0,1\}.\{0,1\}\n|\1_|g" \
<<""
    testflŒÆ˘ˆı››◊‹ıÓÌˇˆÁÓˆfl̈™ˇÏˆıÍÓÌıÓWÌtest

 _ _ _ _t_e_s_t________________________________W__t_e_s_t_

sed교체가 가능한 것 입니다유효하지 않은-길이 문자열. 삭제해도 괜찮지만, sed수락하거나 보관해도 괜찮습니다.여전히. 아 스페이스 맞죠 알겠습니다 그냥 복사해서 터미널에 붙여넣었으니 주인공 4명이(Markdown 코드 블록 들여쓰기용)공간이다.

내가 \newline을 사용하는 이유 중 하나는 패턴 공간에서 유효하지 않은 바이트 시퀀스에 어떤 일이 발생하는지와 관련이 있습니다. 실제 문자와 동일하지 않으면 .일치하지 않고 /^.*$/실패합니다. 개행의 경우 잘못된 바이트 시퀀스 다음의 문자가 .먼저 일치하면 다음과 같습니다.

sed    '/^.*$/!{/\n/D;}'

...이제 지나갈 거야(그러나 GNU는 아닙니다 sed. 먼저 확인했어야 했습니다. sed전에는 AST를 사용하고 있었습니다. 번거롭지 않았습니다.). GNU를 사용하여 전체 패턴 공간을 적용 sed z하십시오 .z

관련 정보