Odpowiedziałem na to pytanie, ale czytając je ponownie, myślę, że go nie zrozumiałem. Czy chcesz przetłumaczyć każdą 0x00z nich na określoną wartość lub na losową wartość z tego 0x00-0xFFzakresu?
Kos
1
@kos do określonej wartości, takiej jak 444444...nieprzypadkowa
Eduard Florinescu,
Odpowiedzi:
18
Poniższy bashkod jest ustawiony do pracy z bajtem reprezentowanym w formacie binarnym . Można go jednak łatwo zmienić, aby obsługiwał ósemkowy , dziesiętny lub szesnastkowy , po prostu zmieniając wartość radix na odpowiednio , lub odpowiednio i ustawiając odpowiednio. r281016b=
EDYCJA - Obsługuje pełny zakres wartości bajtów: hex 00 - FF (kiedy napisałem 00-7F poniżej, rozważałem tylko jednobajtowe znaki UTF-8).
Jeśli na przykład chcesz tylko 4 bajty (znaki w zakresie szesnastkowym 00-7F tylko w formacie UTF-8 „ASCII”) , możesz potokować go do głowy :... | head -c4
Wyjście (4 znaki):
~~~~
Aby zobaczyć wynik w formacie 8-bitowym, potokuj go do xxd(lub dowolnego innego zrzutu bajtów 1 i 0 *):
np. b=10000000i orurowanie do:... | head -c4 | xxd -b
Miałeś na myśli pisać o=$(printf ...)dla drugiej linii?
jwodder
1
@jwodder: Nie, drugi wiersz jest poprawny, jak pokazano. Printf opcja -vpowoduje tthe wyjście bezpośrednio ustawić zmienną o nazwie bezpośrednio po nim; w tym przypadku nazwa zmiennej to o( ósemkowa ) - zwróć uwagę, że -vopcja dotyczy wersji wbudowanej w powłokęprintf (nie wersji / usr / bin / printf )
Peter.O
2
@jwodder Ponadto, ogólnie rzecz biorąc, -vopcja zapewnia, że zmienna zostanie ustawiona dokładnie tak, jak podałeś. $(...)najpierw przekształca dane wyjściowe. Dlatego o=$(printf '\n')nie będzie miał oczekiwanego efektu, podczas gdy printf -vo '\n'ma. (Nie ma to tutaj znaczenia, ponieważ dane wyjściowe są w formie, na którą taka transformacja nie ma wpływu, ale jeśli nie byłeś świadomy tej -vopcji, warto to wiedzieć.)
hvd
18
Nie możesz tego łatwo zrobić.
Możesz rozważyć napisanie własnego modułu jądra zapewniającego takie urządzenie. Nie polecam tego.
Mógłbyś napisać mały program C zapisujący nieskończony strumień tych samych bajtów na jakimś potoku (lub on stdout) lub FIFO.
Możesz użyć tr (1) do czytania /dev/zeroi tłumaczenia każdego 0 bajtu na coś innego.
Możesz użyć może tak (1) , przynajmniej jeśli możesz sobie pozwolić na posiadanie nowego wiersza (lub wpuszczaj go do tr -d '\n'...)
@kojiro: to się nie powiedzie, jeśli spróbujesz przesłać yesstrumień \nznaków. Alternatywą, która obsługuje \n: yes '' | tr '\n' "$c"- gdzie $cmoże być dowolny znak pełnego zakresu znaków ASCII.
Peter.O,
1
@ Peter.O Nie jestem pewien, jak interpretujesz mój komentarz jako coś innego niż dosłowne, statyczne wyrażenie yes 1 | tr -d $'\n'. Przypuszczam, że możesz użyć powłoki, która nie wykonuje $''leczenia odwrotnym ukośnikiem, lub możesz spróbować znaleźć lokalizację, która się zmienia tr -d $'\n', ale jeszcze jej nie znalazłem.
kojiro
@kojiro: Z yes 1 | tr -d $'\n'przyjemnością wydrukujesz strumień 1znaków i prawie każdą inną jednobajtową wartość, ale nie możesz wydrukować strumienia \nznaków. OP chce być w stanie obsłużyć wszystkie wartości bajtów „między 0x01 a 0xFF”
Peter.O
1
loop() { if [ "$1" = $'\n' ]; then yes "$1"; else yes "$1" | tr -d $'\n' ; fi;
PSkocik,
13
Cóż, jeśli dosłownie chcesz to osiągnąć, możesz użyć haka LD_PRELOAD . Podstawową ideą jest przepisanie funkcji z biblioteki C i użycie jej zamiast normalnej.
Oto prosty przykład, w którym nadpisujemy funkcję read () XOR bufora wyjściowego 0x42.
Naiwna implementacja spowodowałaby XOR 0x42 na każdym czytanym pliku, co miałoby niepożądane konsekwencje. Aby rozwiązać ten problem, podłączyłem również funkcję open () , dzięki czemu pobierała deskryptor pliku powiązany z / dev / zero. Następnie wykonujemy XOR w naszej funkcji read () if fd == dev_zero_fd.
Biorąc pod uwagę twoją implementację, możesz mieć symboliczny link z / dev / capbee do / dev / zero, wyszukaj / dev / capbee i zostaw / dev / zero w spokoju. // dev / zero nie będzie taki sam jak / dev / zero.
Robert Jacobs,
1
@RobertJacobs Rzeczywiście. Możemy nawet wygenerować dowiązania symboliczne / dev / 0x01, / dev / 0x02, / dev / 0x03, ... do / dev / zero i przeanalizować nazwę pliku, aby określić maskę bitów do zastosowania.
yoann
11
Pod względem prędkości najszybsze, jakie znalazłem, to:
$ PERLIO=:unix perl -e '$s="\1" x 65536; for(;;){print $s}' | pv -a > /dev/null
[4.02GiB/s]
W moim Debianie perlwydaj 2.13GiB, podczas gdy < /dev/zero8.73GiB. Co może wpłynąć na wydajność?
cuonglm,
@cuonglm, tak, widzę pewne różnice między systemami, ale perljest konsekwentnie szybszy niż inne rozwiązania. Dostaję taką samą przepustowość jak w równoważnym skompilowanym programie C. Test porównawczy dotyczy zarówno aplikacji, jak i harmonogramu systemu. Najbardziej wyróżnia się rozmiar zapisywanych buforów.
Stéphane Chazelas,
@cuonglm Rura również spowalnia. Myślę, że cat /dev/zero| pv -a >/dev/nullda ci również około 2 GiB na sekundę (robi to w moim systemie, podczas gdy < /dev/zero) daje mi około 6GiBps.
PSkocik,
@ StéphaneChazelas Czy mogę zapytać, na jakim systemie jesteś, Stéphane Chazelas? Moje wyniki są dość różne (mogę uzyskać około 2.1GiB z wersji perla). Jestem na Linux ProBook 3.13.0-24-generic #47-Ubuntu SMP Fri May 2 23:30:00 UTC 2014 x86_64 x86_64 x86_64 GNU/LinuxIntel i5 Core w środku.
PSkocik,
1
@PSkocik, Linux 3.16.0-4-amd64 # 1 SMP Debian 3.16.7-ckt9-3 (2015-04-23) x86_64 GNU / Linux, Intel (R) Core (TM) 2 Duo CPU T9600 @ 2.80GHz. Wydaje się, że nowsze jądro robi różnicę (chyba że jest to nowszy perl: v5.20.2)
Stéphane Chazelas
7
Nie ma sensu próbować maskować bitów / xor lub zero bajtów, prawda? Zabranie bajtu i wprowadzenie xorgo do zera nie jest możliwe.
Po prostu utwórz pętlę, która da ci bajty, które chcesz i umieść ją za potokiem lub nazwaną potokiem. Będzie zachowywać się tak samo jak urządzenie postaci (nie marnuje cykli procesora, gdy jest bezczynny):
mkfifo pipe
while : ; do echo -n "a"; done > pipe &
A jeśli chcesz go superoptymalizować, możesz użyć kodu C poniżej:
Początkowo próbowałem użyć putchar w C, ale było to powolne.
PSkocik,
Z ciekawości, dlaczego argc == 1+1zamiast agrc == 2?
Przywróć Monikę - notmaynard
@iamnotmaynard Aby przypomnieć sobie, że jest to 1 dla pliku wykonywalnego wiersza poleceń plus 1 argument. :-D
PSkocik
Ach Tak sądziłem, ale chciałem się upewnić, że nie ma żadnego tajnego powodu.
Przywróć Monikę - notmaynard
„Biorąc bajt i ustawiając go na zero, nie można tego robić”. To nie jest prawdą 0 XOR X == X.
jacwah
5
Czytaj zera, tłumacz każde zero na swój wzór!
Odczytujemy z bajtów zero /dev/zeroi używamy trdo zastosowania maski bitowej do każdego z bajtów, tłumacząc każdy bajt zero:
$ </dev/zero tr '\000' '\176' | head -c 10
~~~~~~~~~~$
Oktal 176 to kod ascii ~, więc otrzymujemy 10 ~. (Na $końcu wyniku wskazuje w mojej powłoce, że nie było końca linii - może wyglądać inaczej dla ciebie)
Stwórzmy 0xFFbajty: Hex 0xFFjest ósemkowy 0377. Zera wiodącego nie ma w trwierszu poleceń; Na końcu hexdumpsłuży do odczytu danych wyjściowych.
W tym miejscu należy użyć kodów ósemkowych znaków zamiast szesnastkowego. Jest to więc zakres od \000ósemkowego \377(taki sam jak 0xFF).
Użyj ascii -xi, ascii -oaby uzyskać tabelę znaków z szesnastkowymi lub ósemkowymi liczbami indeksu.
(Tylko dla tabeli dziesiętnej i szesnastkowej ascii).
Dosyć szybko
Działa dość szybko, w porównaniu do samego zerowania: cat /dev/zerojest tylko cztery razy szybszy, podczas gdy może doskonale wykorzystywać buforowanie IO, co trnie jest możliwe.
$ </dev/zero tr '\000' '\176' | pv -a >/dev/null
[ 913MB/s]
$ </dev/zero cat | pv -a >/dev/null
[4.37GB/s]
Zależy, co chcesz zrobić z danymi i jak elastycznie chcesz z nich korzystać.
W najgorszym przypadku, jeśli potrzebujesz prędkości, możesz zrobić to samo, co / dev / zero, i po prostu skompilować / dev / one, / dev / two, .. / dev / fourtytwo .. i tak dalej na urządzeniach.
W większości przypadków lepiej jest tworzyć dane bezpośrednio tam, gdzie są potrzebne, więc wewnątrz programu / skryptu jako stałą. Dzięki większej ilości informacji ludzie mogą lepiej ci pomóc.
0x00
z nich na określoną wartość lub na losową wartość z tego0x00-0xFF
zakresu?444444...
nieprzypadkowaOdpowiedzi:
Poniższy
bash
kod jest ustawiony do pracy z bajtem reprezentowanym w formacie binarnym . Można go jednak łatwo zmienić, aby obsługiwał ósemkowy , dziesiętny lub szesnastkowy , po prostu zmieniając wartość radix na odpowiednio , lub odpowiednio i ustawiając odpowiednio.r
2
8
10
16
b=
EDYCJA - Obsługuje pełny zakres wartości bajtów: hex 00 - FF (kiedy napisałem 00-7F poniżej, rozważałem tylko jednobajtowe znaki UTF-8).
Jeśli na przykład chcesz tylko 4 bajty
(znaki w zakresie szesnastkowym 00-7F tylko w formacie UTF-8 „ASCII”), możeszpotokowaćgo do głowy :... | head -c4
Wyjście (4 znaki):
Aby zobaczyć wynik w formacie 8-bitowym, potokuj go do
xxd
(lub dowolnego innego zrzutu bajtów 1 i 0 *):np.
b=10000000
i orurowanie do:... | head -c4 | xxd -b
źródło
o=$(printf ...)
dla drugiej linii?-v
powoduje tthe wyjście bezpośrednio ustawić zmienną o nazwie bezpośrednio po nim; w tym przypadku nazwa zmiennej too
( ósemkowa ) - zwróć uwagę, że-v
opcja dotyczy wersji wbudowanej w powłokęprintf
(nie wersji / usr / bin / printf )-v
opcja zapewnia, że zmienna zostanie ustawiona dokładnie tak, jak podałeś.$(...)
najpierw przekształca dane wyjściowe. Dlategoo=$(printf '\n')
nie będzie miał oczekiwanego efektu, podczas gdyprintf -vo '\n'
ma. (Nie ma to tutaj znaczenia, ponieważ dane wyjściowe są w formie, na którą taka transformacja nie ma wpływu, ale jeśli nie byłeś świadomy tej-v
opcji, warto to wiedzieć.)Nie możesz tego łatwo zrobić.
Możesz rozważyć napisanie własnego modułu jądra zapewniającego takie urządzenie. Nie polecam tego.
Mógłbyś napisać mały program C zapisujący nieskończony strumień tych samych bajtów na jakimś potoku (lub on
stdout
) lub FIFO.Możesz użyć tr (1) do czytania
/dev/zero
i tłumaczenia każdego 0 bajtu na coś innego.Możesz użyć może tak (1) , przynajmniej jeśli możesz sobie pozwolić na posiadanie nowego wiersza (lub wpuszczaj go do
tr -d '\n'
...)źródło
yes 1 | tr -d $'\n'
do tego.yes
strumień\n
znaków. Alternatywą, która obsługuje\n
:yes '' | tr '\n' "$c"
- gdzie$c
może być dowolny znak pełnego zakresu znaków ASCII.yes 1 | tr -d $'\n'
. Przypuszczam, że możesz użyć powłoki, która nie wykonuje$''
leczenia odwrotnym ukośnikiem, lub możesz spróbować znaleźć lokalizację, która się zmieniatr -d $'\n'
, ale jeszcze jej nie znalazłem.yes 1 | tr -d $'\n'
przyjemnością wydrukujesz strumień1
znaków i prawie każdą inną jednobajtową wartość, ale nie możesz wydrukować strumienia\n
znaków. OP chce być w stanie obsłużyć wszystkie wartości bajtów „między 0x01 a 0xFF”loop() { if [ "$1" = $'\n' ]; then yes "$1"; else yes "$1" | tr -d $'\n' ; fi;
Cóż, jeśli dosłownie chcesz to osiągnąć, możesz użyć haka LD_PRELOAD . Podstawową ideą jest przepisanie funkcji z biblioteki C i użycie jej zamiast normalnej.
Oto prosty przykład, w którym nadpisujemy funkcję read () XOR bufora wyjściowego 0x42.
Naiwna implementacja spowodowałaby XOR 0x42 na każdym czytanym pliku, co miałoby niepożądane konsekwencje. Aby rozwiązać ten problem, podłączyłem również funkcję open () , dzięki czemu pobierała deskryptor pliku powiązany z / dev / zero. Następnie wykonujemy XOR w naszej funkcji read () if
fd == dev_zero_fd
.Stosowanie:
źródło
Pod względem prędkości najszybsze, jakie znalazłem, to:
Dla porownania:
źródło
perl
wydaj 2.13GiB, podczas gdy< /dev/zero
8.73GiB. Co może wpłynąć na wydajność?perl
jest konsekwentnie szybszy niż inne rozwiązania. Dostaję taką samą przepustowość jak w równoważnym skompilowanym programie C. Test porównawczy dotyczy zarówno aplikacji, jak i harmonogramu systemu. Najbardziej wyróżnia się rozmiar zapisywanych buforów.cat /dev/zero| pv -a >/dev/null
da ci również około 2 GiB na sekundę (robi to w moim systemie, podczas gdy< /dev/zero
) daje mi około 6GiBps.Linux ProBook 3.13.0-24-generic #47-Ubuntu SMP Fri May 2 23:30:00 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
Intel i5 Core w środku.Nie ma sensu próbować maskować bitów / xor lub zero bajtów, prawda? Zabranie bajtu i wprowadzenie
xor
go do zera nie jest możliwe.Po prostu utwórz pętlę, która da ci bajty, które chcesz i umieść ją za potokiem lub nazwaną potokiem. Będzie zachowywać się tak samo jak urządzenie postaci (nie marnuje cykli procesora, gdy jest bezczynny):
A jeśli chcesz go superoptymalizować, możesz użyć kodu C poniżej:
skompiluj i uruchom
Test wydajności:
2,1 GB / s na moim komputerze (nawet nieco szybszym niż
cat /dev/zero | pv -a >/dev/null
)źródło
argc == 1+1
zamiastagrc == 2
?0 XOR X == X
.Czytaj zera, tłumacz każde zero na swój wzór!
Odczytujemy z bajtów zero
/dev/zero
i używamytr
do zastosowania maski bitowej do każdego z bajtów, tłumacząc każdy bajt zero:Oktal 176 to kod ascii
~
, więc otrzymujemy 10~
. (Na$
końcu wyniku wskazuje w mojej powłoce, że nie było końca linii - może wyglądać inaczej dla ciebie)Stwórzmy
0xFF
bajty: Hex0xFF
jest ósemkowy0377
. Zera wiodącego nie ma wtr
wierszu poleceń; Na końcuhexdump
służy do odczytu danych wyjściowych.W tym miejscu należy użyć kodów ósemkowych znaków zamiast szesnastkowego. Jest to więc zakres od
\000
ósemkowego\377
(taki sam jak0xFF
).Użyj
ascii -x
i,ascii -o
aby uzyskać tabelę znaków z szesnastkowymi lub ósemkowymi liczbami indeksu.(Tylko dla tabeli dziesiętnej i szesnastkowej
ascii
).Dosyć szybko
Działa dość szybko, w porównaniu do samego zerowania:
cat /dev/zero
jest tylko cztery razy szybszy, podczas gdy może doskonale wykorzystywać buforowanie IO, cotr
nie jest możliwe.źródło
Zależy, co chcesz zrobić z danymi i jak elastycznie chcesz z nich korzystać.
W najgorszym przypadku, jeśli potrzebujesz prędkości, możesz zrobić to samo, co / dev / zero, i po prostu skompilować / dev / one, / dev / two, .. / dev / fourtytwo .. i tak dalej na urządzeniach.
W większości przypadków lepiej jest tworzyć dane bezpośrednio tam, gdzie są potrzebne, więc wewnątrz programu / skryptu jako stałą. Dzięki większej ilości informacji ludzie mogą lepiej ci pomóc.
źródło
Infinte printf loop
Zastąp ponownie żądanym
\u00
bajtem.while true ; do printf "\u00" ; done | yourapp
Kod C ++:
Kompiluj: zastąp ponownie żądaną
Byte
wartością.g++ -O3 -o bin file.cpp -D Byte=0x01
Posługiwać się
./bin | yourapp
źródło