tr: конвертувати апостроф в ASCII


11

Я намагаюся перетворити правильну єдину лапки в апостроф, використовуючи tr.

tr "`echo -e '\xE2\x80\x99'`" "`echo -e '\x27'`" < a > b

задано закодований файл UTF-8, aякий містить цей приклад:

Were not a different species
All alone?” Jeth mentioned.

OS X використовує BSD trі дає хороший результат:

We're not a different species
“All alone?” Jeth mentioned.

Ubuntu використовує GNU trі дає такий неприємний результат:

We'''re not a different species
''<9C>All alone?''<9D> Jeth mentioned.

Як я можу здійснити цю конверсію в Ubuntu?


Також спробували: tr $ '\ xE2 \ x80 \ x99' $ '\ x27' <a> b з однаковими результатами.
plamtrue

1
Про це добре знати лапки ASCII та Unicode
αғsnιη

2
echo It’s easy | perl -CS -Mutf8 -pe "tr/’/'/"
tchrist

Відповіді:


16

Ви можете спробувати інший інструмент, наприклад sed:

$ sed "s/’/'/g" <a
We're not a different species
“All alone?” Jeth mentioned.

Або, оскільки ми робимо простий переклад, використовуйте yкоманду для sed:

$ sed "y/’/'/" <a
We're not a different species
“All alone?” Jeth mentioned.

GNUtr не працює, імовірно, тому що:

В даний час trповністю підтримує лише однобайтові символи. Врешті-решт він підтримуватиме багатобайтові символи; коли це -C буде зроблено , параметр призведе до того, що він доповнить набір символів, тоді як -c він призведе до доповнення набору значень. Ця відмінність матиме значення лише тоді, коли деякі значення не є символами, і це можливо лише в локалях, що використовують багатобайтові кодування, коли вхід містить помилки кодування.

І є багатобайтовим символом:

$ echo -n \' | wc -c
1
$ echo -n  | wc -c  
3

1
sedнабагато приємніше для такої роботи.
Каз Вулф

2
Щоб пояснити останню частину далі: trце заміна кожного з трьох байтів окремо на ', отже ''', і розбиті послідовності, де вона замінила два з трьох байтів аналогічними символами та . Натомість слід розуміти три байти як разом, що означають один символ, і замість цього.
дельтаб

Для гарного розуміння є багатобайтовим символом, і ми можемо використовувати tr -c '[:print:][:cntrl:]' '-'команду для заміни кожного недрукувального символу , окрім дійсних символів управління, на -. І ви побачите один переклад на 3 байти символів, як ---. хороша точка для багатобайтового характеру.
αғsnιη

9

Якщо ви також хочете перетворити подвійні лапки, а можливо, й інші символи, ви можете використовувати GNUiconv :

$ iconv -f utf-8 -t ascii//translit < a
We're not a different species
"All alone?" Jeth mentioned.

//TRANSLITСуфікс каже , iconvщо для символів поза репертуару цільової кодування (ASCII) тут, він може замінити схожі символи або послідовність автоматично. Без суфікса iconvвідмовиться, як тільки знайде неперекладний характер.

Зауважте, що, //TRANSLITздається, є розширенням GNU: POSIXiconv не підтримує його.


+1. Якщо ви перетворюєте текст з одного набору символів (або кодування) в інший, може бути розумним використовувати інструмент, призначений для цієї мети.
RedGrittyBrick

@deltab ваше рішення також замінює подвійні лапки, які ОП не хочуть замінити.
αғsnιη

@KasiyA Можливо, вони повинні.
gerrit

3

Ви можете використовувати одне з таких awkрішень:

awk '{gsub(/\xE2\x80\x99/, "\x27");print}' file # with Hex ASCII code

awk '{gsub(/’/, "\x27");print}' file

awk '{gsub(/\342\200\231/, "\47");print}'  file # with Octal ASCII code

awk '{gsub(/’/, "\47");print}' file

Або

awk '{gsub(/’/, "'"'"'");print}' file

0

Використовуйте -sваріант tr :

$ echo "We’re not a different species"|tr -s "’" "'"
We're not a different species

Від man tr :

--truncate-set1
          first truncate SET1 to length of SET2

1
ваше рішення також замінює подвійні лапки, які ОП не хочуть їх замінювати
αғsnιη

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