Atau secara lebih umum, bagaimana cara menghapus item dari daftar yang dipisahkan titik dua di variabel lingkungan Bash?
Saya pikir saya telah melihat cara sederhana untuk melakukannya bertahun-tahun yang lalu, menggunakan bentuk yang lebih maju dari ekspansi variabel Bash, tetapi jika demikian saya telah kehilangan jejaknya. Pencarian cepat Google ternyata hanya menemukan sedikit hasil yang relevan dan tidak ada yang saya sebut "sederhana" atau "elegan". Misalnya, dua metode menggunakan sed dan awk, masing-masing:
PATH=$(echo $PATH | sed -e 's;:\?/home/user/bin;;' -e 's;/home/user/bin:\?;;')
PATH=!(awk -F: '{for(i=1;i<=NF;i++){if(!($i in a)){a[$i];printf s$i;s=":"}}}'<<<$PATH)
Apakah tidak ada yang langsung? Apakah ada analogi dengan fungsi split () di Bash?
Pembaruan:
Sepertinya saya perlu meminta maaf atas pertanyaan saya yang sengaja tidak jelas; Saya kurang tertarik untuk menyelesaikan kasus penggunaan tertentu daripada memancing diskusi yang baik. Untungnya, saya mengerti!
Ada beberapa teknik yang sangat pintar di sini. Pada akhirnya, saya telah menambahkan tiga fungsi berikut ke kotak peralatan saya. Keajaiban terjadi di path_remove, yang sebagian besar didasarkan pada penggunaan awk
variabel RS yang cerdas oleh Martin York .
path_append () { path_remove $1; export PATH="$PATH:$1"; }
path_prepend () { path_remove $1; export PATH="$1:$PATH"; }
path_remove () { export PATH=`echo -n $PATH | awk -v RS=: -v ORS=: '$0 != "'$1'"' | sed 's/:$//'`; }
Satu-satunya masalah nyata di sana adalah penggunaan sed
untuk menghilangkan tanda titik dua. Mengingat betapa mudahnya solusi Martin lainnya, saya cukup bersedia menerimanya!
Pertanyaan terkait: Bagaimana cara memanipulasi elemen $ PATH dalam skrip shell?
sumber
WORK=`echo -n ${1} | awk -v RS=: -v ORS=: '$0 != "'${3}'"' | sed 's/:$//'`; eval "export ${2}=${WORK}"
tetapi Anda harus menyebutnya sebagaifunc $VAR VAR pattern
(berdasarkan @ martin-york dan @ andrew-aylett)Jawaban:
Satu menit dengan awk:
Edit: Ini menanggapi komentar di bawah ini:
Edit sebagai jawaban atas masalah keamanan: (yang tidak relevan dengan pertanyaan)
Ini menghapus titik dua tertinggal dengan menghapus entri terakhir, yang secara efektif akan menambah
.
jalur Anda.sumber
PATH
variabel tidak , sebagai aturan khusus, masing menunjukkan direktori saat ini di semua kerang Unix setidaknya sejak V7 Unix dari tahun 1979. Ini masih tidak dalambash
. Periksa manual atau coba sendiri.Retasan kotor saya:
sumber
Karena masalah besar substitusi adalah kasus akhir, bagaimana kalau kasus akhir tidak berbeda dengan kasus lainnya? Jika jalur sudah memiliki titik dua di awal dan akhir, kita cukup mencari string yang diinginkan yang dibungkus dengan titik dua. Karena adanya, kita dapat dengan mudah menambahkan titik dua tersebut dan menghapusnya sesudahnya.
Pesta murni :).
sumber
WORK
danPATH
karena ekspansi variabel terjadi setelah baris diuraikan menjadi beberapa bagian untuk tugas variabel dan eksekusi perintah.REMOVE
mungkin perlu dikutip, atau Anda bisa langsung memasukkan string Anda ke penggantinya jika itu adalah konstanta.Inilah solusi paling sederhana yang bisa saya buat:
Contoh di atas akan menghapus elemen apa pun di $ PATH yang berisi "usr". Anda dapat mengganti "* usr *" dengan "/ home / user / bin" untuk menghapus elemen itu saja.
perbarui per sschuberth
Meskipun menurut saya spasi di a
$PATH
adalah ide yang buruk , berikut adalah solusi yang menanganinya:atau
sumber
Berikut ini satu baris yang, meskipun jawaban yang diterima dan nilai tertinggi saat ini , tidak menambahkan karakter yang tidak terlihat ke PATH dan dapat mengatasi jalur yang berisi spasi:
Secara pribadi, saya juga merasa ini mudah dibaca / dipahami, dan ini hanya melibatkan perintah umum daripada menggunakan awk.
sumber
export PATH=$(p=$(echo $PATH | tr ":" "\0" | grep -v -z "/cygwin/" | tr "\0" ":"); echo ${p%:})
(meskipun bisa dibilang, Anda mungkin ingin bertanya pada diri sendiri mengapa Anda membutuhkan ini, jika Anda melakukannya :))grep -v "^/path/to/remove\$"
ataugrep -v -x "/path/to/remove"
tr
lebih umum daripadaawk
? ;)tr
daripada penerjemahawk
.echo "..."
denganprintf "%s" "..."
untuk itu untuk bekerja pada jalur seperti-e
dan serupa. Lihat stackoverflow.com/a/49418406/102441Berikut adalah solusi yang:
IFS
,menghapus semua kemunculan argumen di
PATH
.sumber
Gali dari file .bashrc saya. Saat Anda bermain-main dengan PATH, dan hilang, awk / sed / grep tidak tersedia :-)
sumber
Opsi bash murni terbaik yang saya temukan sejauh ini adalah sebagai berikut:
Ini didasarkan pada jawaban yang kurang tepat untuk Tambahkan direktori ke $ PATH jika belum ada di Superuser.
sumber
removePath () { PATH=${PATH/":$1"/}; PATH=${PATH/"$1:"/}; }
$PATH
berisi sub-folder dari jalur target (yaitu akan dihapus). Misalnya:a:abc/def/bin:b
->a/bin:b
, kapanabc/def
akan dihapus.Saya baru saja menggunakan fungsi-fungsi dalam distribusi bash, yang tampaknya sudah ada sejak 1991. Fungsi-fungsi ini masih ada dalam paket bash-docs di Fedora, dan pernah digunakan di
/etc/profile
, tetapi tidak lebih ...sumber
Saya memang menulis jawaban untuk ini di sini (menggunakan awk juga). Tapi saya tidak yakin itu yang Anda cari? Setidaknya terlihat jelas bagi saya apa yang dilakukannya, alih-alih mencoba masuk ke dalam satu baris. Untuk satu liner sederhana, itu hanya menghapus barang, saya sarankan
Mengganti adalah
atau (lebih pendek tapi kurang terbaca)
Bagaimanapun, untuk pertanyaan yang sama, dan banyak jawaban berguna, lihat di sini .
sumber
awk '$0 !~ "/bin"'
. Yaitu menjaga baris yang tidak mengandung '/ bin' dengan operator awk!~
.Nah, dalam bash, karena mendukung ekspresi reguler, saya hanya akan melakukan:
sumber
Saya suka tiga fungsi yang ditunjukkan dalam pembaruan @ BenBlank untuk pertanyaan aslinya. Untuk menggeneralisasikannya, saya menggunakan formulir 2-argumen, yang memungkinkan saya menyetel PATH atau variabel lingkungan lain yang saya inginkan:
Contoh penggunaan:
Perhatikan bahwa saya juga menambahkan beberapa tanda kutip untuk memungkinkan pemrosesan nama jalur yang mengandung spasi.
sumber
Apa yang lebih elegan dari awk?
Python! Ini adalah solusi yang lebih mudah dibaca dan dipelihara, dan mudah untuk diperiksa untuk melihat bahwa itu benar-benar melakukan apa yang Anda inginkan.
Katakanlah Anda ingin menghapus elemen jalur pertama?
(Alih-alih menyalurkan dari
echo
,os.getenv['PATH']
akan sedikit lebih pendek, dan memberikan hasil yang sama seperti di atas, tetapi saya khawatir Python mungkin melakukan sesuatu dengan variabel lingkungan itu, jadi mungkin yang terbaik adalah menyalurkannya langsung dari lingkungan yang Anda pedulikan. .)Demikian pula untuk menghapus dari akhir:
Untuk membuat fungsi shell yang dapat digunakan kembali ini, Anda dapat, misalnya, tetap menggunakan file .bashrc Anda:
sumber
Ya, menempatkan titik dua di akhir PATH, misalnya, membuat penghapusan jalur menjadi tidak terlalu kikuk & rawan kesalahan.
sumber
Jika Anda khawatir tentang menghapus duplikat di $ PATH, cara paling elegan, IMHO, adalah dengan tidak menambahkannya sejak awal. Dalam 1 baris:
$ folder dapat diganti dengan apa saja, dan mungkin berisi spasi ("/ home / user / my documents")
sumber
Solusi pesta murni paling elegan yang pernah saya temukan hingga saat ini:
sumber
Sebagian besar solusi yang disarankan lainnya hanya bergantung pada string matching dan tidak memperhitungkan segmen jalan yang berisi nama-nama khusus seperti
.
,..
, atau~
. Fungsi bash di bawah ini menyelesaikan string direktori dalam argumennya dan di segmen jalur untuk menemukan direktori logis yang cocok serta string yang cocok.Uji:
sumber
Linux dari Scratch mendefinisikan tiga fungsi Bash di
/etc/profile
:Ref: http://www.linuxfromscratch.org/blfs/view/svn/postlfs/profile.html
sumber
Saya tahu pertanyaan ini menanyakan tentang BASH, yang seharusnya disukai semua orang, tetapi karena saya menikmati simetri dan terkadang saya diharuskan menggunakan "csh", saya membuat yang setara dengan "path_prepend ()", "path_append ()" dan "path_remove () "solusi elegan di atas.
Intinya adalah bahwa "csh" tidak memiliki fungsi, jadi saya meletakkan skrip shell kecil di direktori bin pribadi saya yang berfungsi seperti fungsi. Saya membuat alias untuk SUMBER skrip tersebut untuk membuat perubahan variabel lingkungan yang ditunjuk.
~ / bin / _path_remove.csh:
~ / bin / _path_append.csh:
~ / bin / _path_prepend.csh:
~ / bin / .cshrc:
Anda dapat menggunakannya seperti ini ...
sumber
Karena ini cenderung cukup bermasalah, karena TIDAK ADA cara yang elegan, saya sarankan untuk menghindari masalah dengan mengatur ulang solusinya: bangun PATH Anda daripada mencoba menghancurkannya.
Saya bisa lebih spesifik jika saya tahu konteks masalah Anda yang sebenarnya. Untuk sementara, saya akan menggunakan software build sebagai konteksnya.
Masalah umum dengan build perangkat lunak adalah kerusakan pada beberapa mesin, yang pada akhirnya disebabkan oleh cara seseorang mengonfigurasi shell default mereka (PATH dan variabel lingkungan lainnya). Solusi elegannya adalah membuat skrip build Anda kebal dengan menentukan lingkungan shell sepenuhnya. Kode skrip build Anda untuk menyetel PATH dan variabel lingkungan lainnya berdasarkan bagian assembling yang Anda kontrol, seperti lokasi compiler, library, alat, komponen, dll. Jadikan setiap item yang dapat dikonfigurasi sesuatu yang dapat Anda setel, verifikasi, dan kemudian gunakan dengan tepat dalam naskah Anda.
Misalnya, saya memiliki build Java bertarget WebLogic berbasis Maven yang saya warisi di perusahaan baru saya. Skrip build terkenal sangat rapuh, dan saya dan karyawan baru lainnya menghabiskan waktu tiga minggu (bukan penuh waktu, hanya di sana-sini, tetapi masih berjam-jam) untuk membuatnya berfungsi di mesin kami. Langkah penting adalah saya mengambil kendali PATH sehingga saya tahu persis Java mana, Maven mana, dan WebLogic mana yang sedang dipanggil. Saya membuat variabel lingkungan untuk menunjuk ke masing-masing alat tersebut, lalu saya menghitung PATH berdasarkan alat tersebut ditambah beberapa lainnya. Teknik serupa menjinakkan pengaturan lain yang dapat dikonfigurasi, sampai kami akhirnya membuat build yang dapat direproduksi.
Ngomong-ngomong, jangan gunakan Maven, Java tidak apa-apa, dan hanya beli WebLogic jika Anda benar-benar membutuhkan pengelompokannya (tetapi sebaliknya tidak, dan terutama fitur kepemilikannya).
Semoga sukses.
sumber
PATH
. Tentu, Anda dapat membuat sendiri, tetapi setiap kali admin Anda memindahkan sesuatu, Anda harus mencari tahu di mana dia meletakkannya. Semacam itu mengalahkan tujuan memiliki seorang admin.Seperti @litb, saya menyumbangkan jawaban untuk pertanyaan " Bagaimana cara memanipulasi elemen $ PATH dalam skrip shell ", jadi jawaban utama saya ada di sana.
Fungsionalitas 'split' dalam
bash
dan turunan Bourne shell lainnya paling baik dicapai dengan$IFS
, pemisah antar-bidang. Misalnya, untuk mengatur argumen posisional ($1
,$2
, ...) dengan unsur-unsur dari PATH, gunakan:Ini akan bekerja dengan baik selama tidak ada spasi di $ PATH. Membuatnya berfungsi untuk elemen jalur yang berisi spasi adalah latihan yang tidak sepele - diserahkan kepada pembaca yang tertarik. Mungkin lebih mudah untuk mengatasinya dengan menggunakan bahasa scripting seperti Perl.
Saya juga memiliki skrip
clnpath
, yang saya gunakan secara ekstensif untuk menyetel PATH saya. Saya mendokumentasikannya dalam jawaban untuk " Bagaimana agar tidak menduplikasi variabel PATH di csh ".sumber
Apa yang membuat masalah ini mengganggu adalah kasus tiang pagar di antara elemen pertama dan terakhir. Masalahnya dapat diselesaikan dengan elegan dengan mengubah IFS dan menggunakan array, tetapi saya tidak tahu cara memasukkan kembali titik dua setelah jalur diubah ke bentuk array.
Berikut adalah versi yang sedikit kurang elegan yang menghapus satu direktori dari hanya
$PATH
menggunakan manipulasi string. Saya sudah mengujinya.sumber
Inilah Perl one-liner:
The
$a
variabel mendapat jalan untuk dihapus. Perintahs
(substitusi) danprint
secara implisit beroperasi pada$_
variabel.sumber
Barang bagus di sini. Saya menggunakan yang satu ini untuk menjaga agar tidak menambahkan penipuan di tempat pertama.
sumber
case ":$PATH:" in (*:"$nodup":*) ;; (*) PATH="$PATH:$nodup" ;; esac
Dengan mengaktifkan perluasan globbing, Anda dapat melakukan hal berikut:
sumber
Globbing satu baris yang diperluas (yah, semacam):
Tampaknya tidak perlu menghindari garis miring di $ 1.
sumber
Menambahkan titik dua ke PATH kita juga bisa melakukan sesuatu seperti:
sumber
Di path_remove_all (oleh proxxy):
sumber
Meskipun ini adalah utas yang sangat lama, saya pikir solusi ini mungkin menarik:
menemukannya di entri blog ini . Saya rasa saya paling suka yang ini :)
sumber
Saya mengambil pendekatan yang sedikit berbeda dari kebanyakan orang di sini dan berfokus secara khusus pada manipulasi string saja, seperti:
Di atas adalah contoh sederhana dari fungsi terakhir yang saya gunakan. Saya juga telah membuat
path_add_before
danpath_add_after
mengizinkan Anda memasukkan jalur sebelum / setelah jalur tertentu yang sudah ada di PATH.Set fungsi lengkap tersedia di path_helpers.sh di dotfiles saya . Mereka sepenuhnya mendukung penghapusan / penambahan / prepending / penyisipan di awal / tengah / akhir dari string PATH.
sumber