Наименее используемый символ-разделитель в обычном тексте <ASCII 128

81

Из соображений кодирования, которые вас ужаснули бы (мне стыдно сказать), мне нужно хранить несколько текстовых элементов в одной строке.

Я выделю их символом.

Какой символ лучше всего использовать для этого, т.е. какой символ с наименьшей вероятностью появится в тексте? Должен быть доступен для печати и, вероятно, меньше 128 в ASCII, чтобы избежать проблем с локалью.

Рахул
источник
44
Пожалуйста, не смущайтесь. Вы должны игнорировать всех людей, которые говорят «ох, это дерьмо, сделайте это вместо этого». Не респонденты задают вопрос «почему», а им решать, как. Меня не волнует, почему ты в таком положении. Я сам был в нескольких. Удачи!
Iain Holder
1
У меня была такая же проблема ... и я использовал PIPE до того, как начал гуглить или переполнить стек ... потому что мне понравилось, как это выглядело --- | ---- как у худого человека.
1
Это зависит от типа текста. В некоторых текстах редко используются символы табуляции, поэтому я часто использую их. Но другие типы текста, включая исходный код, часто используют его. Вы не можете сделать статистику по исходному тексту? Разве вы не можете добавить escape-символы в исходный текст и тем самым использовать в качестве разделителя все, что вам нравится?
hippietrail
не спрашивать и не пытаться намного хуже, чем стесняться задавать какие-либо вопросы. Я здесь, чтобы получить ответ на тот же вопрос, и я горжусь собой, что у меня есть другие люди, разделяющие со мной ту же проблему :)
Теоман Шипахи,
Для тех, кто мог иметь |в своем тексте, у меня действительно был такой случай, когда мне нужно было сократить количество символов до минимума, насколько это возможно. Поскольку в большинстве полей есть строки с интересным текстом, CSV не работал из-за большого количества экранирований. Наш разделитель полей - /|. Косая черта встречается нечасто, но в сочетании с трубкой, с которой вы никогда не столкнетесь. Я использовал движок, который ежедневно пропускает через него много данных. Это никогда не ломалось, и мне никогда не нужно было инкапсулировать одну строку или экранировать специальный символ. В среднем этот механизм сэкономил нам несколько процентов текста.
RLH

Ответы:

34

Предполагая, что по какой-то неловкой причине вы не можете использовать CSV, я бы сказал, что используйте данные. Возьмите несколько примеров данных и выполните простой подсчет символов для каждого значения 0–127. Выберите один из тех, которых не происходит. Если есть слишком большой выбор, возьмите больший набор данных. Написание не займет много времени, и вы получите лучший ответ.

Ответ будет разным для разных проблемных областей, поэтому | (вертикальная черта) часто встречается в сценариях оболочки, ^ - в математических формулах, и то же самое, вероятно, верно для большинства других символов.

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

И что бы вы ни делали, убедитесь, что вы разработали схему побега!

Ник Фортескью
источник
Я бы не стал здесь высмеивать. При экспорте продукта в Magento 2 они объединяют несколько атрибутов в один столбец csv с именем additional_attributes.
стивен
1
Почему бы вам просто не заменить все символы табуляции в тексте четырьмя пробелами и использовать символ табуляции \tв качестве разделителя?
Эли Г.
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.

Разделитель единиц находится в ASCII, и есть поддержка Unicode для его отображения (обычно это «нас» в том же глифе), но многие шрифты не отображают его.

Если вы должны отобразить его, я бы рекомендовал отображать его в приложении после того, как он был проанализирован в поля.

Эдвин Бак
источник
1
вау спасибо. это было именно то, что я искал.
Theunis
22

Наверное | или ^ или ~ вы также можете объединить два символа

SQLMenace
источник
10
использование одного и того же дважды предотвратит недопонимание. Нравится || или ##
roel
17

При использовании разных языков этот символ: ¬

оказался лучшим. Однако я все еще тестирую.

Икарин
источник
1
Мне нравится эта идея, но мне любопытно, можете ли вы создать файл со строками типа «Билли» ¬ «Автомобиль» ¬ «Красный» ¬ «Гараж» ¬ «3» и использовать вырезку. (т.е. $ cut -d "¬" -f1 myfile.delim)
blehman 06
Я добавил этот вопрос в стек здесь: stackoverflow.com/questions/19821639/…
blehman
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, чтобы получить US (0x1F) в Windows.
golfalot
14

Как насчет того, чтобы использовать формат стиля CSV? Символы можно экранировать в стандартном формате CSV, и уже написано множество синтаксических анализаторов.

Алекс Форт
источник
Мне это нравится больше, чем моя идея. +1.
Iain Holder
Я думаю, что запятая считается обычным символом в обычном тексте. Если бы это было так просто, как использование 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
Это действительно лучший ответ здесь, и, как мне кажется, единственно правильный. Это единственный ответ, который нельзя сломать. Все остальные ответы только снижают вероятность того, что ввод нарушает формат, но это очень очень плохой подход. Выбранный ответ справедливо говорит об использовании такой схемы выхода, но как только вы это сделаете, выбор разделителя по существу не имеет значения.
Alfie
Разделитель не совсем актуален. Если вы выберете общий символ - скажем, пробел или букву «e» - ваша экранированная строка действительно станет довольно длинной и трудной для чтения. Лучше всего выбрать необычного персонажа, поэтому я все еще предпочитаю символ трубы для такого рода вещей.
fool4jesus
2

Мы используем ascii 0x7f, который можно использовать для псевдопечати, и он практически никогда не используется.

Джо
источник
2

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

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

Однако CSV, вероятно, лучше для большинства ситуаций.

Coxy
источник
Кодирование base64 - простое решение, однако основная причина использования CSV заключается в том, что вам не нужно повторно анализировать текст, используя base64, вы можете просто полностью изобрести свой собственный формат.
закатывает
1

Что ж, это в некоторой степени будет зависеть от характера вашего текста, но вертикальная полоса 0x7C не часто появляется в тексте.

Джексон
источник
1

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


источник
1

И трубка, и каретка - очевидный выбор. Я хотел бы отметить, что если ожидается, что пользователи будут вводить весь ответ, курсор легче найти на любой клавиатуре, чем канал.

Уилл Джонсон
источник