나는 사용하려고tr
명령은 다음에서 비롯됩니다.가보 도구 상자극복하다현재 한도~의핵심 도구-dc
"임의" 생성기에서 멀티바이트 문자를 "펌프"(옵션 사용) 할 수 있도록 구현되었습니다 (/dev/urandom) 터미널까지. 이것이 이미 있다는 점은 주목할 가치가 있습니다.컴파일된소스에서 시작아치방AUR 사용 실패 후버전.
이를 단순화하기 위해 문자(☠)를 선택하고 해당 8진수 값을 파악해 보겠습니다. 이는 도구 상자에 대해 다음과 같이 표현되어야 하기 때문입니다 tr
.
echo '☠' | hexdump -b # -b for octal
0000000 342 230 240 012
0000004
echo -e '\0342\0230\0240' # uses the "0nnn" format, make sure it prints
☠
8진수 값을 표현하는 방식에 차이가 있습니다불다그리고echo
내장(0nnn) 여기의 도구 상자 tr
(에 에):
문자 "\" 뒤에 1, 2, 3개의 8진 숫자가 오면 해당 숫자로 바이트코드가 제공되는 문자를 나타냅니다. 멀티바이트 문자는 8진수 바이트 시퀀스로 지정할 수 있습니다.
해 보자. 이 -dc
옵션은 단순히 SET1의 보수를 삭제합니다. 세트를 지정하면 해당 세트의 요소를 포함하지 않는 표준 입력의 모든 항목이 삭제됩니다.
echo '012345' | /usr/5bin/tr -dc '456' #sanity check
45 #all good
이제 이것들은:
echo -e '\0342\0230\0240' | /usr/5bin/tr -dc '\342\230\240'
echo -e '☠' | /usr/5bin/tr -dc '☠'
둘 다 one(1)☠을 인쇄해야 합니다. 그렇지 않으면 궁극적으로 다음(더 많은 문자)이 모두 동일한 오류를 생성합니다.
/usr/5bin/tr -dc '\342\230\240' < /dev/urandom
*** Error in `/usr/5bin/tr': double free or corruption (!prev): 0x0000000000d24420 ***
실제로 입력과 SET1에 모두 선택한 문자가 포함될 때마다 오류가 발생하고 가 표시됩니다 -dc
. 이 동작은 시스템 전체에서도 동일합니다.SysV 3rd, 4th, Posix, Posix2001 또는 ucb(BSD)도구 상자에 제공되는 명령 버전입니다. 때로는 tr -dc '1' < /dev/urandom
적절한 segfault나 몇 줄의 출력이 나타나는 경우도 있습니다.
Error in `/usr/5bin/tr': realloc(): invalid pointer: 0x00007f93ee284010 ***
======= Backtrace: =========
/usr/lib/libc.so.6(+0x73f8e)[0x7f93ee338f8e]
/usr/lib/libc.so.6(+0x7988e)[0x7f93ee33e88e]
/usr/lib/libc.so.6(realloc+0x1c8)[0x7f93ee342918]
/usr/5bin/tr[0x401a74]
/usr/5bin/tr[0x400e93]
/usr/lib/libc.so.6(__libc_start_main+0xf0)[0x7f93ee2e5000]
/usr/5bin/tr[0x400f63]
======= Memory map: ========
00400000-00403000 r-xp 00000000 08:21 1579535 /usr/5bin/tr
00602000-00603000 rw-p 00002000 08:21 1579535 /usr/5bin/tr
0067a000-006bc000 rw-p 00000000 00:00 0 [heap]
7f93edc6e000-7f93edc84000 r-xp 00000000 08:21 1448153 /usr/lib/libgcc_s.so.1
7f93edc84000-7f93ede83000 ---p 00016000 08:21 1448153 /usr/lib/libgcc_s.so.1
7f93ede83000-7f93ede84000 rw-p 00015000 08:21 1448153 /usr/lib/libgcc_s.so.1
7f93ede84000-7f93ee2c5000 rw-p 00000000 00:00 0
7f93ee2c5000-7f93ee469000 r-xp 00000000 08:21 1440453 /usr/lib/libc-2.19.so
7f93ee469000-7f93ee669000 ---p 001a4000 08:21 1440453 /usr/lib/libc-2.19.so
7f93ee669000-7f93ee66d000 r--p 001a4000 08:21 1440453 /usr/lib/libc-2.19.so
7f93ee66d000-7f93ee66f000 rw-p 001a8000 08:21 1440453 /usr/lib/libc-2.19.so
7f93ee66f000-7f93ee673000 rw-p 00000000 00:00 0
7f93ee673000-7f93ee694000 r-xp 00000000 08:21 1440340 /usr/lib/ld-2.19.so
7f93ee6eb000-7f93ee874000 r--p 00000000 08:21 1448356 /usr/lib/locale/locale-archive
7f93ee874000-7f93ee877000 rw-p 00000000 00:00 0
7f93ee891000-7f93ee893000 rw-p 00000000 00:00 0
7f93ee893000-7f93ee894000 r--p 00020000 08:21 1440340 /usr/lib/ld-2.19.so
7f93ee894000-7f93ee895000 rw-p 00021000 08:21 1440340 /usr/lib/ld-2.19.so
7f93ee895000-7f93ee896000 rw-p 00000000 00:00 0
7fffed79c000-7fffed7bd000 rw-p 00000000 00:00 0 [stack]
7fffed7e9000-7fffed7eb000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
이것은 내 부분의 컴파일 오류를 의미합니까, 아니면 올바르게 사용하지 않는 것입니까?
기여로수리하다우리는:
echo -e '\0342\0230\0240' | /home/me/bin/trsc -dc '\342\230\240'
echo -e '☠' | /home/me/bin/trsc -dc '☠'
☠
우리가 그래야 하는 것처럼! 하지만:
/home/me/bin/trsc -dc '\342\230\240' < /dev/urandom
선택한 캐릭터가 출력되지 않는다는 점은 여전히 수수께끼입니다...
답변1
나는 그것을 본 적이 있다. 실수. 노력하다:
--- tr.c 6 Sep 2005 23:04:11 -0000 1.10
+++ tr.c 30 May 2014 09:46:33 -0000
@@ -291,7 +291,6 @@
if(c<ccnt) code[c] = d;
if(d<ccnt && sflag) squeez[d] = 1;
}
- free(vect);
while((d = next(&string2)) != NIL) {
if(sflag) squeez[d] = 1;
if(string2.max==NIL && (string2.p==NULL || *string2.p==0))
(이것은 몇 달 전의 간략한 모습이며 이 패치를 통해 앞으로 나아갈 수 있지만 그것이 정확하다고 보장할 수는 없습니다. Apply 를 사용하십시오 patch -l
.)
이제 /dev/urandom
스트림도 제공됩니다.바이트. UTF-8에서는 모든 바이트 시퀀스가 유효한 문자에 매핑되는 것은 아닙니다. 예를 들어 0x41 0x81 0x41은 0x80 0x81
이므로 유효하지 않으므로 >=
0x80바이트를 넘어서 2바이트 이상의 시퀀스로만 나타날 수 있습니다.
☠의 보완 문자 집합에 포함되지 않아 제거되지 않으므로 잘못된 바이트입니다 tr
.
더 나은 방법은 다음과 같습니다.
recode ucs-2..u8 < /dev/urandom | tr -cd ☠
Ucs-2는 U+0000부터 U+FFFF까지의 문자이며, 각 문자는 2바이트로 인코딩되며 /dev/urandom
ucs-2 문자 스트림과 더 비슷해 보입니다. (그러나 U+10000에서 U+10FFFF까지의 문자가 누락되었습니다.)
하지만 여기에는 여전히 포함됩니다.D800..DFFF 프록시 쌍 범위
이것은 mbrtowc(3)
숨막히는 일입니다(적어도 내 버전의 libc에서는).
이러한 코드 포인트는 UTF-16 인코딩용으로 예약되어 있습니다. 예를 들어 d800dc00은 U+10000의 UTF-16BE 인코딩이지만 U+D800 문자 또는 U+DC00은 없습니다. 이러한 문자의 UTF-8 인코딩도 의미가 없습니다(인접한 경우에도).
따라서 먼저 제외해야 합니다.
perl -ne 'BEGIN{$/=\2;binmode STDOUT,":utf8"}
$c = unpack("n",$_); if ($c < 0xd800 || $c > 0xdfff) {
no warnings "utf8"; print chr($c)
}' < /dev/urandom | tr -cd ☠
목표가 UTF-8로 인코딩된 임의의 유니코드 문자 스트림을 얻는 것이라면 허용된 범위(0..0xd7ff, 0xf000..0x10ffff) 내에서 임의의 코드 포인트를 가져와 UTF-8로 변환하는 것이 좋습니다. 을 기반으로 하려는 경우 /dev/urandom
각 코드 포인트에 대해 3바이트(24비트)를 사용할 수 있습니다.
perl -ne 'BEGIN{$/=\3;binmode STDOUT,":utf8"}
$c = unpack("N","\0$_") * 0x10F800 >> 24;
$c+=0x800 if $c >= 0xd800;
do {no warnings "utf8"; print chr($c)}' < /dev/urandom |
tr -cd ☠