2017-02-13 19 views
1

У меня есть файлы JSON, аннотированные комментариями, которые я удаляю перед выполнением операций с использованием jq. Я просто поразил интересную проблему, в которой я получил JSON-файл с комментариями комментариев, который включал некоторые символы кавычек с богатым текстом (hex 93 и hex 94). Мой существующий символ sed . не соответствовал этим символам. Вот демонстрация:Должно ли LC_ALL = C Всегда использоваться для операций с нелокальным концом?

Во-первых, вход:

% echo -e '# \x93text\x94\n{"a":1}' | od -c 
0000000 #  223 t e x t 224 \n { " a " : 1 } 
0000020 \n 
0000021 
% 

А вот преобразование:

% echo -e '# \x93text\x94\n{"a":1}' | sed 's/^\s*#.*//' | od -c 
0000000 223 t e x t 224 \n { " a " : 1 } \n 
0000017 
% 

Обратите внимание, что символ точки в SED выражения не соответствует символ гекс 93 , Однако, если я включаю LC_ALL=C:

% echo -e '# \x93text\x94\n{"a":1}' | LC_ALL=C sed 's/^\s*#.*//' | od -c 
0000000 \n { " a " : 1 } \n 
0000011 
% 

затем символ точки в СЕПГ выражении это соответствует символы с шестигранной 93 и шестигранный 94. Раздел документации sed Locale Considerations говорит о выражениях в скобках, но вышеприведенное поведение, похоже, доказывает, что эта проблема происходит в другом месте.

Интересно отметить, что удаление вместо подстановки не показывать эту проблему:

% echo -e '# \x93text\x94\n{"a":1}' | sed '/^\s*#.*/d' | od -c   
0000000 { " a " : 1 } \n 
0000010 

Учитывая, что я работающий на аннотированных файлов в формате JSON, я думаю, что решение о добавлении LC_ALL=C к SED утверждений разумный.

Итак, мой вопрос: Пользуется LC_ALL=C то, что я всегда хочу, чтобы использовать при выполнении, не локализированных sed преобразования (как это было бы применимо в аннотированных файлов в формате JSON)? Если нет, то какие существуют альтернативы, чтобы избежать проблемы, которую я показал выше?

Моя среда:

  • CentOS 7.3 [ядро-3.10.0-514.6.1.el7.x86_64]
  • СЭД (GNU СЭД) 4.2.2 [SED-4.2.2-5. el7.x86_64]
  • Bash 4.2.46 (1) [Баш-4.2.46-21.el7_3.x86_64]
+0

не проблема под KSH (среда cerftainly разные), но пытается ваша строка я получаю, что может помочь «echo -e» # \ x93text \ x94 \ n {"a": 1} '| sed '/^[[:space:]]*#.*/ s // [ЗДЕСЬ] /' | od -c' дать '0000000 [ЗДЕСЬ] 223 текст 224 \ n {" a 0000020 ": 1} \ n ' so sed оценивается на замену, что конец линии достигнут, а не в выборе – NeronLeVelu

+0

@NeronLeVelu да, это очень нечетное поведение в любом случае. Поскольку веб-страница sed предлагает включать в себя «LC_ALL = C», мне остается задаться вопросом, является ли это обходным путем для ошибки в sed, или если это сложная для понимания функция. –

ответ

0

: C локали это специальный язык, который предназначается, чтобы быть самым простым локали. Вы могли бы также сказать, что, в то время как другие локали для людей, языковой стандарт C предназначен для компьютеров. В локали C, символы одного байта, то набор символов ASCII

В некоторых системах, есть разница с локали POSIX, где, например, порядок сортировки для не-ASCII символов не определен.

поэтому LC_ALL = C - это безопасный способ учета этого несимметричного символа.

см comparaison

с LC, СЭД счетчик как часть символа

echo -e '# \x93text\x94\n{"a":1}' | LC_ALL=C sed 's/[^[:alnum:]]/[HERE:&] /g' | od -c 
0000000 [ H E R E : # ]  [ H E R E : 
0000020 ]  [ H E R E : 223 ]  t e x t [ 
0000040 H E R E : 224 ]  \n [ H E R E : { 
0000060 ]  [ H E R E : " ]  a [ H E R 
0000100 E : " ]  [ H E R E : : ]  1 [ 
0000120 H E R E : } ]  \n 

без LC, СЭД не учитывается как часть характера, чтобы принять во внимание ([[:alnum:]] и [^[:alnum:]] не см 8-битный символ)

echo -e '# \x93text\x94\n{"a":1}' | sed 's/[[:alnum:]]/[HERE:&] /g' | od -c 
0000000 #  223 [ H E R E : t ]  [ H E R 
0000020 E : e ]  [ H E R E : x ]  [ H 
0000040 E R E : t ]  224 \n { " [ H E R E 
0000060 : a ]  " : [ H E R E : 1 ]  } 
0000100 \n 

echo -e '# \x93text\x94\n{"a":1}' | sed 's/[^[:alnum:]]/[HERE:&] /g' | od -c 
0000000 [ H E R E : # ]  [ H E R E : 
0000020 ]  223 t e x t 224 \n [ H E R E : { 
0000040 ]  [ H E R E : " ]  a [ H E R 
0000060 E : " ]  [ H E R E : : ]  1 [ 
0000100 H E R E : } ]  \n 
+0

Итак, вы могли бы подумать, что я могу использовать это как глобальную опцию в своих сценариях ('export LC_ALL = C')? Даже если строковые манипуляции для других целей связаны с данными, специфичными для локали, тогда я предполагаю, что подстановки все равно будут поступать правильно. Например, 's/$ LOCALE_WORD/$ REPLACEMENT /', где два слова специфичны для локали, все равно будут корректно работать с 'LC_ALL = C', правильно? Это побудило бы меня устанавливать это как переменную окружения, а не из каждого раза, когда я использую sed. Как вы думаете? –

+0

Это поведение sed, поэтому добавьте его только в sed (каждый sed в вашей партии), чтобы избежать других непредвиденных действий в другом приложении (просто моя точка зрения и способ, которым я использую его в своей партии, когда эта проблема может возникнуть) – NeronLeVelu

+0

Очень хорошо , Я это сделаю. Спасибо, что нашли время ответить. Отмечая это как принятый ответ. –

 Смежные вопросы

  • Нет связанных вопросов^_^