Пропустить / удалить не ascii персонажа с помощью sed - PullRequest
10 голосов
/ 20 декабря 2011

Chip, Dirkland, DrobæSphere Inc, cdirkland @ hotmail.com, США

Я пытался использовать sed для изменения адресов электронной почты в .csv, но строка выше меня сбивает с толку, используя такие команды:

sed -i 's/[\d128-\d255]//' FILENAME

из этого вопроса stackoverflow

, похоже, не работает, так как я получаю ошибку "недопустимый символ сортировки".

В идеале я вообще не хочу менять этот комбинированный символ АЕ, я бы предпочел sed просто пропустить его, поскольку я не пытаюсь манипулировать этим текстом, а скорее адресами электронной почты. Пока этот AE находится там, хотя он вызывает сбой подстановки sed после одной строки, удаляет символ, и он прекрасно обрабатывает весь файл.

Есть идеи?

Ответы [ 5 ]

5 голосов
/ 17 января 2012
sed -i 's/[^[:print:]]//' FILENAME

Кроме того, это действует как dos2unix

4 голосов
/ 20 декабря 2011

Это может сработать для вас (GNU sed):

echo "Chip,Dirkland,DrobæSphere Inc,cdirkland@hotmail.com,usa" |
sed 's/\o346/a+e/g'
Chip,Dirkland,Droba+eSphere Inc,cdirkland@hotmail.com,usa

Затем сделайте то, что вы должны сделать, и после этого сделайте следующее:

echo "Chip,Dirkland,Droba+eSphere Inc,cdirkland@hotmail.com,usa" | 
sed 's/a+e/\o346/g'
Chip,Dirkland,DrobæSphere Inc,cdirkland@hotmail.com,usa

Если у вас есть хитрые символы встроки и хотите понять, как sed видит их, используя команду l0 (см. здесь ).Также очень полезно для отладки сложных регулярных выражений.

echo "Chip,Dirkland,DrobæSphere Inc,cdirkland@hotmail.com,usa" | 
sed -n 'l0'
Chip,Dirkland,Drob\346Sphere Inc,cdirkland@hotmail.com,usa$
1 голос
/ 02 мая 2016

Я пришел сюда, попробовав эту команду sed s/[\x00-\x1F]/ /g;, которая выдала мне то же сообщение об ошибке.

в этом случае достаточно просто удалить \x00 из сопоставления, получив s/[\x01-\x1F]/ /g;

К сожалению, все вышеперечисленные символы, включая \x7F, включая некоторые другие, запрещены, что можно увидеть с помощью этого короткого сценария:

for (( i=0; i<=255; i++ )); do 
    printf "== $i - \x$(echo "ibase=10;obase=16;$i" | bc) =="
    echo '' | sed -E "s/[\d$i-\d$((i+1))]]//g"
done

Обратите внимание, что проблема заключается только в использовании этих символов для указания диапазона. Вы все еще можете перечислить их все вручную или по сценарию. Например. чтобы вернуться к вашему примеру:

sed -i 's/[\d128-\d255]//' FILENAME

станет

c=; for (( i=128; i<255; i++ )); do c="$c\d$i"; done
sed -i 's/['"$c"']//' FILENAME

что будет означать:

sed -i 's/[\d128\d129\d130\d131\d132\d133\d134\d135\d136\d137\d138\d139\d140\d141\d142\d143\d144\d145\d146\d147\d148\d149\d150\d151\d152\d153\d154\d155\d156\d157\d158\d159\d160\d161\d162\d163\d164\d165\d166\d167\d168\d169\d170\d171\d172\d173\d174\d175\d176\d177\d178\d179\d180\d181\d182\d183\d184\d185\d186\d187\d188\d189\d190\d191\d192\d193\d194\d195\d196\d197\d198\d199\d200\d201\d202\d203\d204\d205\d206\d207\d208\d209\d210\d211\d212\d213\d214\d215\d216\d217\d218\d219\d220\d221\d222\d223\d224\d225\d226\d227\d228\d229\d230\d231\d232\d233\d234\d235\d236\d237\d238\d239\d240\d241\d242\d243\d244\d245\d246\d247\d248\d249\d250\d251\d252\d253\d254\d255]//' FILENAME
0 голосов
/ 03 апреля 2012

В этом случае есть способ просто пропустить символы не-ASCII, не заботясь об удалении.

LANG=C sed /someemailpattern/

См. https://bugzilla.redhat.com/show_bug.cgi?id=440419 и Будет ли sed (и другие) поврежденыфайлы не в формате ASCII? .

0 голосов
/ 20 декабря 2011

Как насчет использования awk для этого. Мы устанавливаем разделитель полей на ничего. Затем переберите каждый символ. Используйте if loop, чтобы проверить, соответствует ли оно нашему character class. Если это так, мы печатаем это, в противном случае мы игнорируем это.

awk -v FS="" '{for(i=1;i<=NF;i++) if($i ~ /[A-Za-z,.@ ]/) printf $i}'

Тест:

[jaypal:~/Temp] echo "Chip,Dirkland,DrobæSphere Inc,cdirkland@hotmail.com,usa" | 
awk -v FS="" '{for(i=1;i<=NF;i++) if($i ~ /[A-Za-z,.@ ]/) printf $i}'
Chip,Dirkland,DrobSphere Inc,cdirkland@hotmail.com,usa

Обновление:

awk -v FS="" '{for(i=1;i<=NF;i++) if($i ~ /[A-Za-z,.@ ]/) printf $i; printf "\n"}' < datafile.csv > asciidata.csv

Я добавил printf "\ n" после цикла, чтобы разделить строки.

...