Найменш використовуваний розділювач у звичайному тексті <ASCII 128


81

З причин кодування, які можуть вас жахнути (мені це дуже соромно сказати), мені потрібно зберігати ряд текстових елементів в одному рядку.

Я розмежую їх за допомогою символу.

Який символ найкраще використовувати для цього, тобто який символ найменше з’являється в тексті? Має бути для друку і, можливо, менше 128 в ASCII, щоб уникнути проблем із мовою.


44
Будь ласка, не соромтеся. Ви повинні ігнорувати всіх людей, які кажуть: "О, це глупний спосіб, зробіть це замість цього". Це не для тих, хто відповідає, щоб запитати, чому, вони для того, щоб відповісти, як. Мені байдуже, чому ти в цій позиції. Я сам був у кількох. Удачі!
Iain Holder

1
У мене була та сама проблема ... і я пішов із PIPE перед тим, як гуглити або переповнювати стек ... тому що мені сподобалось, як це виглядало --- | ---- як шкірна людина.

1
Це залежить від виду тексту. Деякі типи тексту рідко використовують символи табуляції, тому я часто погоджуюсь з цим. Але інші види тексту, включаючи вихідний код, часто використовують його. Чи не можете ви зробити статистику вихідного тексту? Чи не можете ви додати символи переходу у вихідний текст і тим самим використовувати що-небудь, що вам подобається, як роздільник?
hippietrail

не запитувати і не намагатись набагато гірше, ніж соромитися задавати будь-які питання. Я тут, щоб отримати відповідь на те саме питання, і я пишаюся собою, що у мене є інші люди, які поділяють зі мною ту ж проблему :)
Teoman shipahi

Для тих, хто міг би мати |в своєму тексті, я насправді мав такий випадок, коли мені потрібно було якомога менше зводити символи до мінімуму. Оскільки більшість полів містять рядки з цікавим текстом, CSV не працює через велику кількість екранувань. Наш роздільник поля /|. Коса риса є лише помірною, але в парі з трубою, на яку ви ніколи не натрапляєте. Я використовую механізм, який отримує багато даних через нього щодня. Це ніколи не ламалося, і мені ніколи не потрібно було інкапсулювати жодний рядок або уникати спеціального символу. В середньому цей механізм заощадив нам кілька відсотків тексту.
RLH

Відповіді:


34

Якщо припустити, що з якоїсь незручної причини ви не можете використовувати CSV, я б сказав, перейдіть із даними. Візьміть кілька зразків даних і зробіть простий підрахунок символів для кожного значення 0-127. Виберіть один із тих, який не відбувається. Якщо вибору занадто багато, отримайте більший набір даних. Писання не займе багато часу, і ви отримаєте найкращу для вас відповідь.

Відповідь буде різною для різних проблемних доменів, тому | (pipe) є загальним у сценаріях оболонки, ^ є загальним у математичних формулах, і те саме, ймовірно, справедливо для більшості інших символів.

Я особисто думаю, що пішов би на | (трубопровід), якщо вибрати вибір, але найбезпечнішим є використання реальних даних.

І що б ви не робили, переконайтесь, що ви розробили схему втечі!


Я б тут не висміював. При експорті товару magento 2 вони об’єднують ряд атрибутів у єдиний стовпець, який називається csv additional_attributes.
Стівен

1
Чому б вам просто не замінити всі символи табуляції в тексті на чотири пробіли і не використовувати символ табуляції \tяк роздільник?
Elie G.,

35

Я вибрав би "Розділювач одиниць" ASCII код "США": ASCII 31 (0x1F)

За старих, старих часів більшість речей виконувались послідовно, без довільного доступу. Це означало, що декілька контрольних кодів були вбудовані в 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.

Unit Separator знаходиться в ASCII, і для його відображення є підтримка Unicode (як правило, це "us" у тому самому гліфі), але багато шрифти його не відображають.

Якщо вам потрібно відобразити його, я б рекомендував відображати його в додатку, після того, як він буде проаналізований на поля.


1
вау, дякую це було саме те, що я шукав.
Теуніс

22

Ймовірно | або ^ або ~ ви також можете поєднати два символи


10
використання двічі одного і того ж запобіжить будь-яке непорозуміння. Як || або ##
roel

17

При використанні різних мов цей символ: ¬

виявився найкращим. Однак я все ще тестую.


1
Мені ця ідея подобається, але мені цікаво, чи можете ви подати файл, що містить рядки типу "Billy" ¬ "Car" ¬ "Red" ¬ "Garage" ¬ "3" і використовувати cut. (тобто $ cut -d "¬" -f1 myfile.delim)
blehman

Я додав це питання стека тут: stackoverflow.com/questions/19821639 / ...
Блехман

15

Ви сказали "для друку", але це може містити такі символи, як вкладка (0x09) або стрічка форми (0x0c). Я майже завжди вибираю вкладки, а не коми для розділених файлів, оскільки коми іноді можуть з'являтися в тексті.

(Цікаво, що таблиця ascii має символи GS (0x1D), RS (0x1E) та US (0x1F) для розділювачів груп, записів та одиниць, якими б вони не були.)

Якщо під поняттям "для друку" ви маєте на увазі символ, який користувач міг розпізнати і легко ввести, я б пішов за конвеєром | символ першої, з кількома іншими дивними персонажами ( @або ~чи ^або \чи лапки , які я не можу увійти тут) як можливість. Ці символи +=!$%&*()-'":;<>,.?/здаються такими, що вони, швидше за все, траплятимуться під час введення користувачем. Щодо підкреслення _та хешування #та дужок, {}[]я їх не знаю.


14
Стандартна таблиця кодів ASCII включає чотири коди управління, спеціально розроблені для цієї мети, як зазначено вище Джейсоном С. Це: 28 FSРозділювач файлів, Розділювач 29 GSгруп, Розділювач 30 RSзаписів, Розділювач 31 USодиниць. На жаль, майже ніхто їх не використовує, хоча саме для цього вони були призначені. Особисто я ненавиджу файли формату CSV, тому що так багато людей не продумують щось і роблять безлад, з яким нам, програмістам, доводиться стикатися, якщо ми хочемо підтримувати їх формати файлів.
deegee

3
@deegee, це, мабуть, найкраща відповідь тут. Якщо дані не містять двійковий або нестандартний ascii / unicode, це завжди буде працювати будь-якою мовою. Ви повинні перетворити це на звичайну відповідь.
dhj

@rahul чи маєш ти повноваження позначити це як прийняту відповідь? Найбільш корисний при роботі з введеними користувачами даними, повними сміття. Примітка для інших: ALT + 31, щоб отримати США (0x1F) у Windows.
гольфалот

14

Як щодо того, щоб використовувати формат стилю CSV? Символи можна екранувати у стандартному форматі CSV, і вже створено багато парсерів.


Мені це подобається більше, ніж моя ідея. +1.
Іен Холдер

Я думаю, кома вважається загальним символом у звичайному тексті. Якби це було так просто, як використання CSV, я сумніваюся, що потрібно було б задати питання ...
Джей,

CSV має справу з комами в звичайному тексті, а також з кількома іншими проблемами. Тож не має значення, що в тексті вже є кома. IIRC розміщує текст у лапках та уникає лапок.
Джеремі Френч

@ Джеремі: абсолютно правильно. Ось стаття у Вікіпедії, де згадується, як працює схема виходу: en.wikipedia.org/wiki/Comma-separated_values
rmeador

1
Якщо сказати прямо: CVS буде розглядати всі ті проблеми, про які ви не думали, і переконайтесь, що вам не доведеться виправляти своє "рішення" кожні два тижні, оскільки воно ламається через якусь непередбачену інформацію.
Аарон Дігулла

9

Чи можете ви використовувати символ труби? Це, як правило, наступний найпоширеніший роздільник після рядків, розділених комами або табуляцією. Навряд чи більшість текстів міститиме конвеєр, і ord ('|') повертає мені 124, тож, здається, це відповідає вашим вимогам.


8

Для швидкого втечі я використовую такі речі: скажімо, ви хочете об'єднати str1, str2 і str3, що я роблю:

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

потім, щоб отримати оригінальне використання:

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","@");

Примітка: порядок заміни важливий

його незламний і простий у реалізації


2
Це справді найкраща відповідь тут і єдина правильна imo. Це єдина відповідь, яку не можна зламати. Усі інші відповіді лише знижують ймовірність того, що вхід порушить формат, але це дуже поганий підхід. Вибрана відповідь справедливо говорить про використання такої схеми втечі, але як тільки ви зробите вибір роздільника, по суті не має значення.
Альфі

Розмежувач не зовсім не має значення. Якщо ви виберете загального символу - скажімо пробіл або букву "е" - ваш рядок, що втік, справді стане досить довгим і важким для читання. Краще вибрати незвичного персонажа, саме тому я все ще віддаю перевагу символу труби для подібних речей.
crazy4jesus


2

Ми використовуємо ascii 0x7f, який є псевдодрукувальним і навряд чи коли-небудь з’являється у звичайному використанні.


2

Це може бути добре чи погано (як правило, погано) залежно від ситуації та мови, але майте на увазі, що ви завжди можете Base64 кодувати все це. Тоді вам не доведеться турбуватися про втечу та скасування різних шаблонів на кожній стороні, і ви можете просто відокремити та розділити рядки на основі символу, який не використовується у вашій коди коду Base64.

Мені довелося вдатися до цього рішення, стикаючись із розміщенням документів XML у властивостях / вузлах XML. Властивості взагалі не можуть мати блоків CDATA, а вузли не працюють, оскільки CDATA, очевидно, не може мати в собі подальших блоків CDATA без порушення структури.

CSV, мабуть, є кращою ідеєю для більшості ситуацій.


Кодування base64 - це просте рішення, однак основною причиною використання CSV є те, що вам не потрібно переробляти текст, використовуючи base64, ви можете просто повністю винайти власний формат.
котиться

1

Ну, це певною мірою залежатиме від природи вашого тексту, але вертикальна смужка 0x7C не надто часто з’являється в тексті.


1

Не думаю, що я коли-небудь бачив амперсанд, за яким слідує кома в природному тексті, але ви можете спочатку перевірити файл, чи не містить роздільник, і якщо так, скористайтеся альтернативою. Якщо ви хочете завжди мати можливість знати, що використовуваний вами роздільник не спричинить конфлікту, виконайте цикл, перевіряючи файл на потрібний вам роздільник, а якщо він існує, подвойте рядок, поки файл більше не має відповідності . Не має значення, чи є подібні рядки, оскільки ваша програма буде шукати лише точні збіги роздільників.


1

І труба, і карет - очевидний вибір. Я б зауважив, що якщо від користувачів очікується набрати повну відповідь, Caret легше знайти на будь-якій клавіатурі, ніж pipe.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.