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 cutmetod 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 foojest 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 cutsamego. 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
mktemptworzy względnie bezpieczny plik tymczasowy, do którego można potokować dane cutwyjściowe.
Możesz używać slurp z POSIX Awk:
cut -b1 file | awk 'BEGIN{RS="";getline<"-";print>ARGV[1]}' file
Cóż, ponieważ cutprodukuje mniej danych wyjściowych niż czyta, możesz:
cut -c1 < file 1<> file
Oznacza to, że stdin powinien być fileotwarty w trybie tylko do odczytu, a stdout fileotwarty w trybie odczytu + zapisu bez obcinania ( <>).
W ten sposób cutpo prostu nadpisze plik na siebie. Pozostawia jednak pozostałą część pliku niezmienioną. Na przykład, jeśli filezawiera:
foo
bar
Dane wyjściowe staną się:
f
b
bar
f\nb\nZastąpiły foo\n, ale barnadal istnieje. Po tym musisz przyciąć plikcut skończyć zakończeniu.
Za pomocą ksh93moż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 perltylko w tym celu jest nieco przesadne, szczególnie biorąc pod uwagę, że perlmożna z łatwością wykonać taką cutpracę, 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.
.oldmetoda wprowadzania zmian w miejscu,echo "$(cut -d , -f 1,3 <foo)" > foo