Odpowiedzi:
Nie możesz Użyj ed lub GNU sed lub perl albo zrób to, co robią za kulisami, czyli utworzenie nowego pliku dla zawartości.
ed
, przenośny:
ed foo <<EOF
1,$s/^\([^,]*\),\([^,]*\),\([^,]*\).*/\1,\3/
w
q
EOF
GNU ANTYLOPA sed
:
sed -i -e 's/^\([^,]*\),\([^,]*\),\([^,]*\).*/\1,\3/' foo
Perl:
perl -i -l -F, -pae 'print @F[1,3]' foo
cut
, tworzenie nowego pliku (zalecane, ponieważ jeśli twój skrypt zostanie przerwany, możesz go ponownie uruchomić):
cut -d , -f 1,3 <foo >foo.new &&
mv -f foo.new foo
cut
, zastępując plik na miejscu (zachowuje własność i uprawnienia foo
, ale potrzebuje ochrony przed przerwami):
cp -f foo foo.old &&
cut -d , -f 1,3 <foo.old >foo &&
rm foo.old
Polecam użycie jednej z cut
metod opartych na bazie . W ten sposób nie polegasz na żadnym niestandardowym narzędziu, możesz użyć najlepszego narzędzia do pracy i kontrolować zachowanie podczas przerwania.
cut -d , -f 1,3 foo > foo.new
rm foo
mv foo.new foo
rm foo
. I nie powinieneś dzwonić rm foo
, ponieważ mv foo.new foo
jest atomowy: usuwa starą wersję i jednocześnie umieszcza nową.
Moreutils pakiet z Ubuntu (a także debian ) posiada program o nazwie sponge
, która sort-of rozwiązuje również problem.
Z gąbki męskiej:
sponge odczytuje standardowe wejście i zapisuje je w określonym pliku. W przeciwieństwie do przekierowania powłoki, gąbka wchłania wszystkie dane wejściowe przed otwarciem pliku wyjściowego. Umożliwia to zwężenie potoków, które odczytują i zapisują do tego samego pliku.
Co pozwoli ci zrobić coś takiego:
cut -d <delim> -f <fields> somefile | sponge somefile
Nie sądzę, że jest to możliwe przy użyciu cut
samego. Nie mogłem tego znaleźć na stronie o człowieku lub stronie informacyjnej. Możesz zrobić coś takiego jak
mytemp=$(mktemp) && cut -d" " -f1 file > $mytemp && mv $mytemp file
mktemp
tworzy względnie bezpieczny plik tymczasowy, do którego można potokować dane cut
wyjściowe.
Możesz używać slurp z POSIX Awk:
cut -b1 file | awk 'BEGIN{RS="";getline<"-";print>ARGV[1]}' file
Cóż, ponieważ cut
produkuje mniej danych wyjściowych niż czyta, możesz:
cut -c1 < file 1<> file
Oznacza to, że stdin powinien być file
otwarty w trybie tylko do odczytu, a stdout file
otwarty w trybie odczytu + zapisu bez obcinania ( <>
).
W ten sposób cut
po prostu nadpisze plik na siebie. Pozostawia jednak pozostałą część pliku niezmienioną. Na przykład, jeśli file
zawiera:
foo
bar
Dane wyjściowe staną się:
f
b
bar
f\nb\n
Zastąpiły foo\n
, ale bar
nadal istnieje. Po tym musisz przyciąć plikcut
skończyć zakończeniu.
Za pomocą ksh93
można to zrobić za pomocą <>;
operatora, który działa podobnie, <>
z tym wyjątkiem, że jeśli polecenie się powiedzie, ftruncate()
wywoływany jest w deskryptorze pliku. Więc:
cut -c1 < file 1<>; file
W przypadku innych powłok należy wykonać ftruncate()
inne czynności, takie jak:
{ cut -c1 < file; perl -e 'truncate STDOUT, tell STDOUT';} 1<> file
chociaż wywoływanie perl
tylko w tym celu jest nieco przesadne, szczególnie biorąc pod uwagę, że perl
można z łatwością wykonać taką cut
pracę, jak:
perl -pi -e '$_ = substr($_, 0, 1)' file
Uważaj, że przy wszystkich metodach, które wymagają faktycznego przepisywania w miejscu, jeśli operacja zostanie przerwana w połowie, skończysz na uszkodzonym pliku. Użycie tymczasowego drugiego pliku pozwala uniknąć tego problemu.
.old
metoda wprowadzania zmian w miejscu,echo "$(cut -d , -f 1,3 <foo)" > foo