Najrzadziej używany znak separatora w zwykłym tekście <ASCII 128

81

Z powodów związanych z kodowaniem, które mogłyby cię przerazić (jestem zbyt zawstydzony, by powiedzieć), muszę przechowywać wiele elementów tekstowych w jednym ciągu.

Wyznaczę je za pomocą znaku.

Którego znaku najlepiej użyć do tego, tj. Który znak ma najmniejsze prawdopodobieństwo pojawienia się w tekście? Musi być możliwy do wydrukowania i prawdopodobnie mniej niż 128 w ASCII, aby uniknąć problemów z lokalizacją.

Rahul
źródło
44
Proszę, nie wstydź się. Powinieneś zignorować wszystkich ludzi, którzy mówią „ooh, to bzdury, zrób to zamiast tego”. Nie do respondentów należy pytanie dlaczego, ale do nich należy odpowiedź, w jaki sposób. Nie obchodzi mnie, dlaczego jesteś w tej pozycji. Sam byłem w kilku. Powodzenia!
Iain Holder
1
Miałem ten sam problem ... i poszedłem z PIPE przed wygooglowaniem lub przepełnieniem stosu ... ponieważ podobał mi się wygląd --- | ---- jak skinney.
1
To zależy od rodzaju tekstu. Niektóre rodzaje tekstu rzadko używają znaków tabulacji, więc często z tym korzystam. Jednak inne rodzaje tekstu, w tym kod źródłowy, często go używają. Nie możesz zrobić statystyk w tekście źródłowym? Czy nie możesz dodać znaków zmiany znaczenia do tekstu źródłowego i tym samym użyć czegoś, co lubisz jako separatora?
hippietrail
nie pytać i nie próbować, jest znacznie gorsze niż wstyd zadawania jakichkolwiek pytań. Jestem tu po odpowiedź na to samo pytanie i jestem z siebie dumny, że mam kilka innych osób, które mają ten sam problem ze mną :)
Teoman shipahi
Dla tych, którzy mogli mieć |w tekście znak , miałem taki przypadek, w którym musiałem ograniczyć liczbę znaków do minimum. Ponieważ większość pól zawierała ciągi znaków z interesującym tekstem, CSV nie działał z powodu dużej liczby znaków ucieczki. Naszym ogranicznikiem pól jest /|. Cięcie jest tylko umiarkowanie powszechne, ale w połączeniu z rurą, na którą nigdy nie wpadniesz. Używam silnika, który codziennie otrzymuje dużo danych. To nigdy się nie zepsuło i nigdy nie musiałem hermetyzować pojedynczego ciągu ani uciekać przed specjalnym znakiem. Średnio ten mechanizm pozwolił nam zaoszczędzić kilka procent tekstu.
RLH

Odpowiedzi:

34

Zakładając, że z jakiegoś zawstydzającego powodu nie możesz używać CSV, powiedziałbym, że idź z danymi. Weź przykładowe dane i oblicz prostą liczbę znaków dla każdej wartości od 0 do 127. Wybierz jedną z tych, które nie występują. Jeśli wybór jest zbyt duży, uzyskaj większy zestaw danych. Pisanie nie zajmie dużo czasu, a otrzymasz najlepszą dla siebie odpowiedź.

Odpowiedź będzie inna dla różnych dziedzin problemowych, więc | (pionowa kreska) jest powszechna w skryptach powłoki, ^ jest powszechna w formułach matematycznych i to samo jest prawdopodobnie prawdą w przypadku większości innych znaków.

Osobiście uważam, że wybrałbym | (potok), jeśli masz wybór, ale korzystanie z prawdziwych danych jest najbezpieczniejsze.

I cokolwiek robisz, upewnij się, że opracowałeś schemat ucieczki!

Nick Fortescue
źródło
Nie wyśmiewałbym się tutaj. W eksporcie produktu Magento 2 łączą szereg atrybutów w jedną kolumnę CSV o nazwie additional_attributes.
Stephen
1
Dlaczego po prostu nie zastąpisz wszystkich znaków tabulatora w tekście czterema spacjami i nie użyjesz znaku tabulacji \tjako separatora?
Elie G.
35

Wybrałbym „Separator jednostek”, kod ASCII „US”: ASCII 31 (0x1F)

W dawnych czasach większość rzeczy była wykonywana seryjnie, bez przypadkowego dostępu. Oznaczało to, że kilka kodów kontrolnych zostało osadzonych w ASCII.

ASCII 28 (0x1C) File Separator - Used to indicate separation between files on a data input stream.
ASCII 29 (0x1D) Group Separator - Used to indicate separation between tables on a data input stream (called groups back then).
ASCII 30 (0x1E) Record Separator - Used to indicate separation between records within a table (within a group).  These roughly map to a tuple in modern nomenclature.
ASCII 31 (0x1F) Unit Separator - Used to indicate separation between units within a record.  The roughly map to fields in modern nomenclature.

Separator jednostek jest w formacie ASCII i jest obsługiwany przez Unicode do jego wyświetlania (zazwyczaj „nas” w tym samym glifie), ale wiele czcionek go nie wyświetla.

Jeśli musisz go wyświetlić, polecam wyświetlenie go w aplikacji, po przeanalizowaniu go na pola.

Edwin Buck
źródło
1
wow, dziękuję. to było dokładnie to, czego szukałem.
Theunis
22

Prawdopodobnie | lub ^ lub ~ możesz też połączyć dwa znaki

SQLMenace
źródło
10
dwukrotne użycie tego samego zapobiegnie nieporozumieniom. Jak || lub ##
roel
17

W przypadku używania różnych języków ten symbol: ¬

okazały się najlepsze. Jednak wciąż testuję.

Icarin
źródło
1
Podoba mi się ten pomysł, ale jestem ciekawy, czy jesteś w stanie złożyć ciągi zawierające ciągi takie jak „Billy” ¬ „Samochód” ¬ „Czerwony” ¬ „Garaż” ¬ „3” i użyć cięcia. (tj. $ cut -d "¬" -f1 myfile.delim)
blehman
Dodałem to pytanie do stosu tutaj: stackoverflow.com/questions/19821639/...
blehman
15

Powiedziałeś „drukowalny”, ale może to obejmować takie znaki, jak tabulacja (0x09) lub wysuw strony (0x0c). Prawie zawsze wybieram tabulatory zamiast przecinków dla plików rozdzielanych, ponieważ przecinki czasami pojawiają się w tekście.

(Co ciekawe, tabela ascii zawiera znaki GS (0x1D), RS (0x1E) i US (0x1F) dla separatorów grup, rekordów i jednostek, cokolwiek to jest / były.)

Jeśli przez „drukowalny” masz na myśli znak, który użytkownik mógłby rozpoznać i łatwo wpisać, wybrałbym potok | najpierw symbol, z kilkoma innymi dziwnymi znakami ( @lub ~lub ^lub \, lub lewym przyciskiem, których nie mogę tutaj wprowadzić) jako możliwą. +=!$%&*()-'":;<>,.?/Wydaje się, że te znaki będą częściej pojawiać się podczas wprowadzania danych przez użytkownika. Jeśli chodzi o podkreślenie _i hash #oraz nawiasy {}[], to nie wiem.

Jason S.
źródło
14
Standardowa tabela kodów ASCII zawiera cztery kody sterujące zaprojektowane specjalnie do tego celu, jak wspomniał Jason S. powyżej. Są to: 28 FSSeparator plików, Separator 29 GSgrup, Separator 30 RSrekordów, Separator 31 USjednostek. Niestety, prawie nikt ich nie używa, chociaż dokładnie do tego zostały przeznaczone. Osobiście nie znoszę plików w formacie CSV, ponieważ tak wiele osób nie myśli o wszystkim i robi bałagan, z którym my, programiści, musimy sobie radzić, jeśli chcemy obsługiwać ich formaty plików.
deegee
3
@deegee to prawdopodobnie najlepsza odpowiedź tutaj. O ile dane nie zawierają binarnego lub niestandardowego formatu ascii / unicode, to zawsze będzie działać w dowolnym języku. Powinieneś to zmienić w zwykłą odpowiedź.
dhj
@rahul czy masz uprawnienia do oznaczenia tej odpowiedzi jako zaakceptowanej? Najbardziej przydatne, gdy masz do czynienia z danymi wejściowymi użytkownika pełnymi śmieci. Uwaga dla innych: ALT + 31, aby uzyskać US (0x1F) w systemie Windows.
golfalot
14

A może używasz formatu CSV? Znaki mogą zostać zmienione w standardowym formacie CSV, a jest już napisanych wiele parserów.

Alex Fort
źródło
Podoba mi się to bardziej niż mój pomysł. +1.
Iain Holder
Myślę, że przecinek liczy się jako zwykły znak w normalnym tekście. Gdyby to było tak proste, jak użycie CSV, wątpię, czy istniałaby potrzeba zadania pytania ...
Jay
csv zajmuje się przecinkami w zwykłym tekście, a także kilkoma innymi problemami. Nie ma więc znaczenia, że ​​w tekście jest już przecinek. IIRC umieszcza tekst w cudzysłowie i wyłącza cudzysłowy.
Jeremy French
@Jeremy: dokładnie tak. Oto artykuł z Wikipedii, w którym wspomina się, jak działa schemat ucieczki: en.wikipedia.org/wiki/Comma-separated_values
rmeador
1
Mówiąc wprost: CVS zajmie się wszystkimi problemami, o których nie pomyślałeś i upewni się, że nie będziesz musiał naprawiać swojego „rozwiązania” co dwa tygodnie, ponieważ zepsuje się ono z powodu nieprzewidzianych danych wejściowych.
Aaron Digulla
9

Czy możesz użyć symbolu fajki? Zwykle jest to następny najpopularniejszy separator po ciągach rozdzielanych przecinkami lub tabulatorami. Jest mało prawdopodobne, że większość tekstu zawiera pionową kreskę, a ord ('|') zwraca dla mnie 124, więc wydaje się, że pasuje do twoich wymagań.

Sójka
źródło
8

Do szybkiego ucieczki używam takich rzeczy: powiedz, że chcesz połączyć str1, str2 i str3, co robię to:

delimitedStr=str1.Replace("@","@a").Replace("|","@p")+"|"+str2.Replace("@","@a").Replace("|","@p")+"|"+str3.Replace("@","@a").Replace("|","@p");

następnie, aby odzyskać oryginalne użycie:

splitStr=delimitedStr.Split("|".ToCharArray());
str1=splitStr[0].Replace("@p","|").Replace("@a","@");
str2=splitStr[1].Replace("@p","|").Replace("@a","@");
str3=splitStr[2].Replace("@p","|").Replace("@a","@");

uwaga: kolejność wymiany jest ważna

jest niezniszczalny i łatwy do wdrożenia

Mohammad Amin
źródło
2
To naprawdę najlepsza odpowiedź tutaj i jedyna poprawna imo. To jedyna odpowiedź, której nie można złamać. Wszystkie inne odpowiedzi tylko obniżają prawdopodobieństwo złamania formatu przez dane wejściowe, ale jest to bardzo, bardzo słabe podejście. Wybrana odpowiedź słusznie mówi o zastosowaniu takiego schematu ucieczki - ale gdy już dokonasz wyboru separatora, w zasadzie nie ma to znaczenia.
Alfie
Ogranicznik nie jest zupełnie nieistotny. Jeśli wybierzesz typowy znak - powiedz spację lub literę „e” - Twój znak ucieczki stanie się naprawdę długi i trudny do odczytania. Najlepiej wybrać nietypową postać, dlatego nadal wolę symbol fajki do tego typu rzeczy.
fool4jesus
2

Używamy ascii 0x7f, który jest pseudo-drukowalny i prawie nigdy nie pojawia się w regularnym użyciu.

Joe
źródło
2

Może to być dobre lub złe (zwykle złe) w zależności od sytuacji i języka, ale pamiętaj, że zawsze możesz zakodować całość w Base64. Nie musisz się wtedy martwić o ucieczkę i cofanie różnych wzorów z każdej strony, a możesz po prostu oddzielić i podzielić ciągi na podstawie znaku, który nie jest używany w twoim zestawie znaków Base64.

Musiałem uciekać się do tego rozwiązania, gdy miałem do czynienia z umieszczaniem dokumentów XML we właściwościach / węzłach XML. Właściwości nie mogą w ogóle zawierać bloków CDATA, a węzły uciekły, ponieważ CDATA oczywiście nie może mieć w sobie dalszych bloków CDATA bez uszkodzenia struktury.

Jednak CSV jest prawdopodobnie lepszym pomysłem w większości sytuacji.

Coxy
źródło
kodowanie base64 jest prostym rozwiązaniem, jednak głównym powodem używania CSV jest to, że nie musisz ponownie analizować tekstu, używając base64 równie dobrze możesz po prostu całkowicie wymyślić własny format.
rolki
1

Cóż, będzie to w pewnym stopniu zależeć od natury twojego tekstu, ale pionowy pasek 0x7C nie pojawia się zbyt często w tekście.

Jackson
źródło
1

Wydaje mi się, że nigdy nie widziałem znaku ampersand, po którym następuje przecinek w tekście naturalnym, ale możesz najpierw sprawdzić plik, aby zobaczyć, czy zawiera separator, a jeśli tak, użyj alternatywy. Jeśli chcesz zawsze wiedzieć, że separator, którego używasz, nie spowoduje konfliktu, wykonaj pętlę sprawdzającą plik pod kątem żądanego separatora, a jeśli istnieje, podwajaj ciąg, aż plik nie będzie już pasował . Nie ma znaczenia, czy istnieją podobne ciągi, ponieważ Twój program będzie szukał tylko dokładnych dopasowań separatora.


źródło
1

Zarówno fajka, jak i daszek są oczywistym wyborem. Chciałbym zauważyć, że jeśli oczekuje się, że użytkownicy wpiszą całą odpowiedź, daszek jest łatwiejszy do znalezienia na dowolnej klawiaturze niż potok.

Will Johnson
źródło