Un comando di esempio che mostra il sintomo: sed 's/./@/' <<<$'\xfc'fallisce, perché byte 0xfcnon è un carattere UTF-8 valido.
Si noti, al contrario, GNU sed (Linux, ma installabile anche su macOS) passa semplicemente attraverso il byte non valido, senza segnalare un errore.
L'uso della risposta precedentemente accettata è un'opzione se non ti dispiace perdere il supporto per la tua locale (se sei su un sistema americano e non hai mai bisogno di trattare con personaggi stranieri, potrebbe andare bene).
Tuttavia, lo stesso effetto può essere dovuto ad-hoc per un singolo comando solo :
LC_ALL=C sed -i "" 's|"iphoneos-cross","llvm-gcc:-O3|"iphoneos-cross","clang:-Os|g' Configure
Nota: Ciò che conta è una efficace LC_CTYPE impostazione C, quindi LC_CTYPE=C sed ...sarebbe normalmente anche il lavoro, ma se LC_ALLcapita di essere impostato (a qualcosa di diverso C), avrà la precedenza singole LC_*variabili -Categoria quali LC_CTYPE. Pertanto, l'approccio più solido è quello di impostare LC_ALL.
Tuttavia, l'impostazione (efficacemente) LC_CTYPEdi Ctrattare le stringhe come se ogni byte fosse il proprio carattere ( non viene eseguita alcuna interpretazione basata sulle regole di codifica), senza tener conto della codifica UTF-8 multibyte su richiesta che OS X utilizza per impostazione predefinita , in cui i caratteri stranieri hanno codifiche multibyte .
In breve: l' impostazione LC_CTYPEinC modo che la shell e le utility riconoscano solo le lettere inglesi di base come lettere (quelle nell'intervallo ASCII a 7 bit), in modo che i caratteri stranieri. non saranno trattati come lettere , causando, ad esempio, conversioni maiuscole / minuscole.
Ancora una volta, questo può andare bene se non è necessario abbinare caratteri con codifica multibyte come ée se si desidera semplicemente passare tali caratteri attraverso .
Se questo è insufficiente e / o si desidera comprendere la causa dell'errore originale (inclusa la determinazione di quali byte di input hanno causato il problema) ed eseguire conversioni di codifica su richiesta, leggere di seguito.
Il problema è che la codifica del file di input non corrisponde alla shell.
Più specificamente, il file di input contiene caratteri codificati in un modo che non è valido in UTF-8 (come affermato da @Klas Lindbäck in un commento) - questo è ciò che il sedmessaggio di errore sta cercando di dire invalid byte sequence.
Molto probabilmente, il file di input utilizza una codifica a 8 bit a byte singolo comeISO-8859-1 , utilizzata frequentemente per codificare le lingue "dell'Europa occidentale".
Esempio:
La lettera accentata àha un punto di codice Unicode 0xE0(224) - lo stesso di in ISO-8859-1. Tuttavia, a causa della natura della codifica UTF-8 , questo singolo punto di codice è rappresentato come 2 byte 0xC3 0xA0, mentre il tentativo di passare il singolo byte non0xE0 è valido in UTF-8.
Ecco una dimostrazione del problema utilizzando la stringa voilàcodificata come ISO-8859-1, con il àrappresentato come un byte (tramite una stringa bash quotata ANSI-C ( $'...') che utilizza \x{e0}per creare il byte):
Si noti che il sedcomando è effettivamente una no-op che passa semplicemente attraverso l'input, ma ne abbiamo bisogno per provocare l'errore:
# -> 'illegal byte sequence': byte 0xE0 is not a valid char.
sed 's/.*/&/' <<<$'voil\x{e0}'
Per ignorare semplicemente il problema , è LCTYPE=Cpossibile utilizzare l'approccio sopra :
# No error, bytes are passed through ('á' will render as '?', though).
LC_CTYPE=C sed 's/.*/&/' <<<$'voil\x{e0}'
Se si desidera determinare quali parti dell'input causano il problema , provare quanto segue:
# Convert bytes in the 8-bit range (high bit set) to hex. representation.
# -> 'voil\x{e0}'
iconv -f ASCII --byte-subst='\x{%02x}' <<<$'voil\x{e0}'
L'output mostrerà tutti i byte con il bit alto impostato (byte che superano l'intervallo ASCII a 7 bit) in forma esadecimale. (Si noti, tuttavia, che include anche sequenze multibyte UTF-8 correttamente codificate: sarebbe necessario un approccio più sofisticato per identificare specificamente i byte non validi in UTF-8.)
Esecuzione della codifica delle conversioni su richiesta :
L'utilità standard iconvpuò essere utilizzata per convertire in ( -t) e / o da ( -f) codifiche;iconv -lelenca tutti quelli supportati.
Esempi:
Converti FROM ISO-8859-1nella codifica attiva nella shell (basata su LC_CTYPE, che è UTF-8basata di default), basandosi sull'esempio sopra:
# Converts to UTF-8; output renders correctly as 'voilà'
sed 's/.*/&/' <<<"$(iconv -f ISO-8859-1 <<<$'voil\x{e0}')"
Tieni presente che questa conversione ti consente di abbinare correttamente i caratteri stranieri :
# Correctly matches 'à' and replaces it with 'ü': -> 'voilü'
sed 's/à/ü/' <<<"$(iconv -f ISO-8859-1 <<<$'voil\x{e0}')"
Per convertire l'input BACK in ISO-8859-1dopo l'elaborazione, è sufficiente reindirizzare il risultato a un altro iconvcomando:
sed 's/à/ü/' <<<"$(iconv -f ISO-8859-1 <<<$'voil\x{e0}')" | iconv -t ISO-8859-1