Perintah berikut ini dengan benar mengubah isi 2 file.
sed -i 's/abc/xyz/g' xaa1 xab1
Tapi yang perlu saya lakukan adalah mengubah beberapa file seperti itu secara dinamis dan saya tidak tahu nama file tersebut. Saya ingin menulis perintah yang akan membaca semua file dari direktori saat ini dimulai dengan xa*
dan sed
harus mengubah konten file.
sed -i 's/abc/xyz/g' xa*
?Jawaban:
Lebih baik:
karena tidak ada yang tahu berapa banyak file di sana, dan mudah untuk melanggar batas baris perintah.
Inilah yang terjadi ketika ada terlalu banyak file:
sumber
for
perintah. Untuk melindungi diri dari hal itu, Anda harus menggunakanfind ... | xargs ...
for
daripada yang dilakukannya untukecho
ataugrep
?"$i"
alih-alih$i
menghindari pemisahan kata pada nama file dengan spasi. Kalau tidak, ini sangat bagus.for
adalah bagian dari sintaks bahasa, bahkan bukan hanya builtin. Sebabsed -i 's/old/new' *
, perluasan*
SEMUA harus dilewatkan sebagai argumen untuk sed, dan saya cukup yakin ini harus terjadi sebelumsed
proses bahkan dapat dimulai. Menggunakanfor
loop, argumen penuh (ekspansi*
) tidak pernah dilewatkan sebagai perintah, hanya disimpan dalam memori shell dan diulangi. Saya tidak punya referensi untuk ini sama sekali, sepertinya ada bedanya. (Saya ingin mendengar dari seseorang yang lebih berpengetahuan ...)Saya terkejut tidak ada yang menyebutkan argumen -exec untuk ditemukan, yang ditujukan untuk jenis penggunaan-kasus ini, meskipun akan memulai proses untuk setiap nama file yang cocok:
Atau, orang dapat menggunakan xargs, yang akan meminta lebih sedikit proses:
Atau lebih mudah gunakan
+
varian exec daripada;
di find untuk memungkinkan find menyediakan lebih dari satu file per panggilan subproses:sumber
find ./ -type f -name 'xa*' -exec sed -i '' 's/asd/dsg/g' {} \;
itu adalah lokasi untuk perintah find./
dan sepasang tanda kutip tunggal-i
untuk OSX../
sama dengan.
dan setelah-i
hanya memiliki parameter backupsuffix.-exec
pilihan untuk menemukan bersama dengan{} +
cukup untuk memecahkan masalah seperti yang dinyatakan, dan harus baik untuk sebagian besar kebutuhan. Tetapixargs
merupakan pilihan yang lebih baik secara umum karena juga memungkinkan pemrosesan paralel dengan-p
opsi. Saat ekspansi gumpalan Anda cukup besar untuk melebihi panjang baris perintah Anda, Anda kemungkinan juga akan mendapat manfaat dari peningkatan kecepatan selama menjalankan berurutan.Anda bisa menggunakan grep dan sed secara bersamaan. Ini memungkinkan Anda untuk mencari subdirektori secara rekursif.
sumber
grep -v
untuk menghindari folder gitgrep -rl <old> . | grep -v \.git | xargs sed -i 's/<old>/<new>/g'
Perintah-perintah itu tidak akan berfungsi di default
sed
yang menyertai Mac OS X.Dari
man 1 sed
:Mencoba
dan
Keduanya bekerja dengan baik.
sumber
@PaulR memposting ini sebagai komentar, tetapi orang-orang harus melihatnya sebagai jawaban (dan jawaban ini paling cocok untuk kebutuhan saya):
Ini akan bekerja untuk jumlah file sedang, mungkin dalam urutan puluhan, tetapi mungkin tidak pada urutan jutaan .
sumber
sed -i 's|auth-user-pass nordvpn.txt|auth-user-pass /etc/openvpn/nordvpn.txt|g' *.ovpn
.Cara lain yang lebih fleksibel adalah dengan menggunakan
find
:sumber
Saya menggunakan
find
untuk tugas serupa. Ini cukup sederhana: Anda harus menyampaikannya sebagai argumen untuksed
seperti ini:sed -i 's/EXPRESSION/REPLACEMENT/g' `find -name "FILE.REGEX"`
Dengan cara ini Anda tidak perlu menulis loop yang rumit, dan mudah dilihat, file mana yang akan Anda ubah, jalankan saja
find
sebelum Anda jalankansed
.sumber
kamu bisa membuat
' xxxx ' teks yang Anda cari dan akan menggantinya dengan ' yyyy '
sumber
Jika Anda dapat menjalankan skrip, inilah yang saya lakukan untuk situasi serupa:
Menggunakan kamus / hashMap (array asosiatif) dan variabel untuk
sed
perintah, kita bisa mengulang array untuk mengganti beberapa string. Termasuk wildcard diname_pattern
akan memungkinkan untuk mengganti di tempat dalam file dengan pola (ini bisa menjadi sesuatu sepertiname_pattern='File*.txt'
) di direktori tertentu (source_dir
). Semua perubahan ditulis dilogfile
dalamdestin_dir
Pertama, array pasangan dideklarasikan, masing-masing pasangan adalah string pengganti, kemudian
WHAT1
akan diganti untukFOR1
danOTHER_string_to replace
akan diganti untukstring replaced
dalam fileFile.txt
. Dalam loop array dibaca, anggota pertama dari pasangan tersebut diambil sebagaireplace_what=$i
dan yang kedua sebagaireplace_for=$j
. Thefind
pencarian perintah dalam direktori nama file (yang mungkin berisi wildcard) dansed -i
Menggantikan perintah dalam file yang sama (s) apa yang didefinisikan sebelumnya. Akhirnya saya menambahkangrep
arahan ulang ke logfile untuk mencatat perubahan yang dibuat dalam file.Ini bekerja untuk saya
GNU Bash 4.3
sed 4.2.2
dan berdasarkan jawaban VasyaNovikov untuk Loop over tuple di bash .sumber