Dlaczego base64 ciągu zawiera „\ n”?

84
$ echo -n "apfjxkic-omyuobwd339805ak:60a06cd2ddfad610b9490d359d605407" | base64
YXBmanhraWMtb215dW9id2QzMzk4MDVhazo2MGEwNmNkMmRkZmFkNjEwYjk0OTBkMzU5ZDYwNTQw
Nw==

Wyjście ma wcześniej zwrot Nw==. Jaki jest prawidłowy sposób generowania base64 w systemie Linux?

zrzut ekranu terminala

Tiina
źródło
5
Czy jesteś pewien, że dane wyjściowe zawierają nowy wiersz, a nie tylko zawijanie okna? To polecenie działało dla mnie dobrze na Macu. Z jakiego systemu operacyjnego korzystasz?
Ian
47
RFC 2045, który zdefiniował Base64, WYMAGA nowej linii po 76 znakach (maks.). Co sprawia, że ​​uważasz, że twój przykład nie jest właściwy?
MSalters
24
@MSalters RFC 4648 specjalnie rozwiązuje ten problem. Wdrożenia NIE WOLNO dodawać wysuwu wiersza do danych zakodowanych w podstawie, chyba że specyfikacja odnosząca się do tego dokumentu wyraźnie nakazuje koderom podstawowym dodawanie wysuwu wiersza po określonej liczbie znaków. => ta implementacja jest niepoprawna zgodnie z RFC 4648, o ile twierdzi, że tworzy „zwykłe” wyjście zakodowane w base64. Co ciekawsze, strony GNU base64 (pytanie?) Odnoszą się konkretnie do RFC 3548, która również domyślnie nie określa zawijania, a która RFC 4648 jest przestarzała.
Bob
4
@Bob: RFC mają nieco mniejszy szacunek dla stabilności API; narzędzie base64 nie może po prostu zmienić formatu wyjściowego bez przerywania skryptów.
MSalters
2
@MSalters Nie mogę być pewien, że starsza wersja nie istnieje, ale GNU base64 został napisany w 2004 roku, a AFAICT zawsze twierdził, że przestrzega RFC 3548. RFC 3548 zawiera tę samą klauzulę „NIE MOŻNA dodawać kanałów”. Więc nawet pierwotna implementacja była „zła”. Przynajmniej jego implementacja nie odpowiada dokumentacji. W każdym razie zapytałeś, dlaczego przykład OP jest poprawny, i odesłałeś do RFC; moją odpowiedzią jest poprawny RFC, który faktycznie określa base64 w izolacji. Jeśli twoja odpowiedź brzmi „z powodów historycznych”, niech tak będzie, ale OP nie jest tutaj źle.
Bob

Odpowiedzi:

151

Próbować:

echo -n "apfjxkic-omyuobwd339805ak:60a06cd2ddfad610b9490d359d605407" | base64 -w 0

Od man base64:

-w, --wrap=COLS
Zawijaj zakodowane linie po COLSznaku (domyślnie 76). Użyj, 0aby wyłączyć zawijanie linii.

Kamil Maciorowski
źródło
17
O rany, zawsze to przepuszczałem tr. Dobrze wiedzieć, że istnieje „właściwy sposób”.
Score_Under
Wyjaśnienie, dlaczego wartość domyślna nie jest zerem, jest dla mnie zagadką.
Dherik
1
@Dherik Myślę, że to dzięki uprzejmości narzędzi do przetwarzania tekstu. base64koduje dowolne dane binarne jako tekst. Narzędzia, które oczekują tekstu, zwykle czytają jedną linię na raz i mogą nie radzić sobie dobrze z bardzo długimi liniami . Jeśli -w 0byłby domyślny, domyślnie byłby tylko jeden wiersz tekstu; niezwykle długa linia, jeśli dane wejściowe były duże. Lepiej jest domyślnie zawijać. Myślę, że 76został wybrany, ponieważ jest to niewiele mniej niż 80jest to faktyczny standard dla terminali .
Kamil Maciorowski
@KamilMaciorowski dziękuję za informację. Za każdym razem, gdy użyłem base64polecenia, musiałem przekazać -w 0(a kiedy zapomniałem, dziwne rzeczy mogą się zdarzyć ...), więc to domyślne zachowanie było dla mnie bardzo dziwne.
Dherik
54

Jest to gorsze niż odpowiedź Kamila w systemach obsługujących tę -wopcję base64, ale w przypadkach, gdy nie jest to możliwe (np. Alpine Linux, Arch Linux initramfshook itp.), Możesz ręcznie przetworzyć dane wyjściowe base64:

base64 some_file.txt | tr -d \\n

To podejście oparte na brutalnej sile; zamiast zmuszać program do współpracy, używam trdo bezładnego usuwania każdej nowej linii na standardowym wyjściu.

Score_Under
źródło