Chciałbym zastąpić zestaw znaków odpowiednimi znakami z innego zestawu, coś takiego:
original set: ots
"target" set: u.x
foobartest → fuubar.ex.
Tłumaczenia / transliteracje takie jak ta są specjalnością tr
polecenia:
$ echo 'foobartest' | tr 'ots' 'u.x'
fuubar.ex.
Niestety tr
nie obsługuje zmiany plików w miejscu, tak jak sed
robi.
Chciałbym użyć, sed
więc nie muszę ponownie wymyślać koła plików tymczasowych żonglerki.
tr
(poprawnie) ignoruje rekurencję w zestawach zastępczych:echo 'abc' | tr ab bx
→bxc
. Prymitywne rozwiązanie może to zaszkodzić,xxc
ponieważ ponownie stosuje tłumaczenie do znaków, które już zostały przetłumaczone.sed
przeciwieństwie do GNUtr
potrafi transliterować znaki wielobajtowe)Odpowiedzi:
sed
may
polecenie, które działa tak jaktr
:y
Komenda jest częścią POSIXsed
specyfikacja , więc powinien działać na prawie każdej platformie.A skoro tak
sed
, możesz poprosić go o zastąpienie pliku edytowaną wersją, oszczędzając ci kłopotliwego biznesu plików tymczasowych (pod warunkiem, że twoja implementacjased
obsługuje-i
opcję, która nie jest określona przez POSIX):źródło
sed
„s”, nie oznacza, że inne funkcje również są. ;) Na liście mailingowej Vima znajduje się wątek na temat znalezieniay/abc/def/
odpowiednika; najlepsza opcja wydaje się być:%call setline(".", tr(getline("."),"abc","def"))
.Jeśli tak jak w twoim przypadku, transliterujesz znaki bez zmiany ich rozmiaru (zresztą niektóre implementacje, takie jak GNU,
tr
obsługują tylko znaki jednobajtowe), możesz:Oznacza to, że
tr
nadpisują plik nad sobą.To lepiej niż
sed -i
na kilku kontach:Wadą jest to, że jeśli zostanie przerwany, plik zostanie w połowie przetłumaczony (w tym przypadku można go jednak uruchomić ponownie, aby go zakończyć). Niektóre
sed
implementacje poradziłyby sobie z tym poprawnie, upewniając się, że oryginalny plik pozostaje niezmieniony, chyba że polecenie się powiedzie.źródło
echo 'abc' | tr ab bx
.tr
a w naszym środowisku PXE o dużym obciążeniu symbolicznymsed -i
czekanie się wydarzy…: /iconv -t cp437
wydaje się bardziej odpowiednie do tego.iconv
pęka, gdy plik wejściowy zawiera już bajty zakodowane w cp437 lub mieszaninę wielu kodowań. Chociaż jest to preferowane w ogólnym przypadku, bardziej niezawodne jest ręczne zastępowanie w tym przypadku.Jako kolejną alternatywę, jeśli twoim głównym problemem jest brak obsługi zmiany plików w miejscu, możesz zainteresować się
sponge
narzędziem z pakietu moreutils :zapisze do
file
, ale będzie otwartyfile
do zapisu po zakończeniu wprowadzania danych. Z strony podręcznika :O ile nie masz naprawdę dużych plików, których nie można przechowywać w pamięci,
sponge
może Ci pomóc.źródło
sponge
jest to, że nadal się zastępuje,file
jeśli siętr
nie powiedzie (na przykład, jeśli miałeś dostęp do zapisu, ale nie masz dostępu do odczytufile
)cat file >; file
operator ksh93, który zapisuje dane wyjściowe do pliku tymczasowego, którego nazwa zostaje zmieniona na miejsce docelowe tylko wtedy, gdy polecenie się powiedzie (ale jak tosed -i
, że tworzy nowy plik zamiast nadpisywania oryginału).