2011-12-20 27 views
10

Chip, Dirkland, DrobæSphere Inc, cdirkland @ hotmail.com, Stati Uniti d'AmericaSkip/rimuovere caratteri non-ascii con sed

Ho cercato di usare sed per modificare gli indirizzi di posta elettronica in un file .csv ma la linea sopra di me continua a inciampare, utilizzando i comandi come:

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

from this stackoverflow question

non sembra funzionare come ottengo un errore 'non valida carattere collazione'.

Idealmente non voglio cambiare quel carattere combinato di AE, preferirei sed semplicemente saltarci sopra mentre non sto cercando di manipolare quel testo ma piuttosto gli indirizzi email. Finché questo AE è presente ma causa la mancata sostituzione di sed dopo una riga, cancella il carattere e elabora l'intero file.

Qualche idea?

risposta

4

Questo potrebbe funzionare per voi (GNU SED):

echo "Chip,Dirkland,DrobæSphere Inc,[email protected],usa" | 
sed 's/\o346/a+e/g' 
Chip,Dirkland,Droba+eSphere Inc,[email protected],usa 

poi fare quello che devi fare e dopo ripristinare fare:

echo "Chip,Dirkland,Droba+eSphere Inc,[email protected],usa" | 
sed 's/a+e/\o346/g' 
Chip,Dirkland,DrobæSphere Inc,[email protected],usa 

Se hai caratteri difficili nelle stringhe e si desidera per capire come li vede sed utilizzare il comando l0 (vedere here). Molto utile anche per il debug di espressioni regolari difficili.

echo "Chip,Dirkland,DrobæSphere Inc,[email protected],usa" | 
sed -n 'l0' 
Chip,Dirkland,Drob\346Sphere Inc,[email protected],usa$ 
+0

+1 per il 'l0'. Esiste anche un altro script 'sedsed.py', disponibile [qui] (http://aurelio.net/sedsed/). Utile per ispezionare gli spazi 'pattern' e' hold'. Potrebbe non essere d'aiuto in questo caso, ma un utile strumento di debug comunque. :) –

+0

che il comando sed -n 'l0' è interessante, ciò che viene stampato per società è: Drob \ 357 \ 277 \ 275Sphere Inc – xref

+0

e non riesco ancora a ottenere gli esempi sopra per lavorare con esso, forse il personaggio (che mostra come un AE in Windows LibreOffice ma da nessun'altra parte) è in realtà un personaggio speciale che dice che non può essere rappresentato in unicode? http://www.fileformat.info/info/unicode/char/fffd/index.htm – xref

0

Per quanto riguarda l'utilizzo di awk per questo. Abbiamo impostato il Field Separator su zero. Quindi loop su ogni personaggio. Utilizzare un if loop per verificare se corrisponde al nostro character class. Se lo stampiamo noi lo ignoriamo.

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

prova:

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

Aggiornamento:

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

Ho aggiunto printf "\ n" dopo il ciclo di mantenere le linee si separano.

+0

Grazie Jaypal, come sarebbe questo essere modificato se si voleva processare datafile.csv e output asciidata.csv? – xref

+0

Ho aggiornato la risposta. Spero possa aiutare! –

+0

Se si desidera solo estrarre l'indirizzo di posta elettronica dal proprio file di input, 'awk' può farlo in un attimo senza alcuna regex complessa. Fammi sapere come funziona. –

4
sed -i 's/[^[:print:]]//' FILENAME 

Inoltre, questo agisce come dos2unix

+0

Non funziona. [: print:] non è lo stesso di ASCII, ad es. 'ü' è stampabile ma non ASCII. –

1

Sono venuto qui provando questo comando sed s/[\x00-\x1F]/ /g;, che mi ha dato lo stesso messaggio di errore.

in questo caso è sufficiente semplicemente per rimuovere il \x00 dalle regole di confronto, cedendo s/[\x01-\x1F]/ /g;

Purtroppo sembra che tutti i caratteri sopra e compreso \x7F e alcuni altri sono consentito, come si può vedere con questo breve script:

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 

Si noti che il problema è solo l'uso di quei caratteri per specificare un intervallo. Puoi ancora elencarli tutti manualmente o per script. Per esempio. di tornare al tuo esempio:

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

sarebbe diventato

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

che si tradurrebbe a:

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

"_Probabilmente sembra che tutti i caratteri sopra e inclusi \ x7F e alcuni altri siano disabilitati_". Grazie! Questo spiegava il motivo per cui ricevo l'errore "Carattere collation non valido". – xpt