Saya memiliki skrip shell dengan kode ini:
var=`hg st -R "$path"`
if [ -n "$var" ]; then
echo $var
fi
Tetapi kode kondisional selalu dijalankan, karena hg st
selalu mencetak setidaknya satu karakter baris baru.
- Apakah ada cara sederhana untuk menghapus spasi
$var
(sepertitrim()
dalam PHP )?
atau
- Apakah ada cara standar untuk menangani masalah ini?
Saya bisa menggunakan sed atau AWK , tetapi saya ingin berpikir ada solusi yang lebih elegan untuk masalah ini.
$ var=$(echo)
$ [ -n $var ]; echo $? #undesired test return
0
$ [[ -n $var ]]; echo $?
1
echo " This is a string of char " | xargs
. Jika Anda namun memiliki satu kutipan dalam teks Anda dapat melakukan hal berikut:echo " This i's a string of char " | xargs -0
. Perhatikan bahwa saya menyebutkan xarg terbaru (4.6.0)test=`echo`; if [ -n "$test" ]; then echo "Not empty"; fi
, ini akantest=`echo "a"`; if [ -n "$test" ]; then echo "Not empty"; fi
- jadi harus ada lebih dari sekadar baris baru di akhir.echo $A | sed -r 's/( )+//g'
;Jawaban:
Mari kita definisikan variabel yang berisi spasi spasi awal, jejak, dan menengah:
Cara menghapus semua spasi putih (dilambangkan dengan
[:space:]
dalamtr
):Cara menghapus spasi putih saja:
Cara menghapus trailing space saja:
Cara menghapus spasi depan dan akhir - rangkai
sed
:Atau, jika bash Anda mendukungnya, Anda dapat menggantinya
echo -e "${FOO}" | sed ...
dengansed ... <<<${FOO}
, seperti: (untuk mengekstrak spasi putih):sumber
tr
dansed
perintah dengan[[:space:]]
. Perhatikan bahwased
pendekatan ini hanya akan bekerja pada input satu baris . Untuk pendekatan yang bekerja dengan input multi-line dan juga menggunakan fitur built-in bash, lihat jawabannya oleh @bashfu dan @GuruM. Versi umum, inline dari solusi @Nicholas Sushkin akan terlihat seperti ini:trimmed=$([[ " test test test " =~ [[:space:]]*([^[:space:]]|[^[:space:]].*[^[:space:]])[[:space:]]* ]]; echo -n "${BASH_REMATCH[1]}")
alias trim="sed -e 's/^[[:space:]]*//g' -e 's/[[:space:]]*\$//g'"
ke Anda~/.profile
memungkinkan Anda untuk menggunakanecho $SOMEVAR | trim
dancat somefile | trim
.sed
solusi yang hanya menggunakan ekspresi tunggal daripada dua:sed -r 's/^\s*(\S+(\s+\S+)*)\s*$/\1/'
. Ini memotong whitespace memimpin dan mengikuti, dan menangkap urutan karakter wh-spasi yang dipisahkan whitespace di tengah. Nikmati!|
, sehingga tetap sebagai satu ekspresi tunggal, bukan beberapa.Jawaban sederhana adalah:
Xargs akan melakukan pemotongan untuk Anda. Ini satu perintah / program, tanpa parameter, mengembalikan string yang dipangkas, semudah itu!
Catatan: ini tidak menghapus semua ruang internal jadi
"foo bar"
tetap sama; TIDAK menjadi"foobar"
. Namun, beberapa ruang akan diringkas menjadi satu ruang, jadi"foo bar"
akan menjadi"foo bar"
. Selain itu tidak menghapus karakter garis akhir.sumber
xargs echo
hanya untuk menjadi verbose tentang apa yang saya lakukan, tetapi xargs sendiri akan menggunakan gema secara default.sed 's/ *$//'
sebagai alternatif. Anda dapat melihatxargs
baris seperti ini:echo -n "hey thiss " | xargs | hexdump
Anda akan melihat0a73
yanga
merupakan baris baru. Jika Anda melakukan hal yang sama dengansed
:echo -n "hey thiss " | sed 's/ *$//' | hexdump
Anda akan melihat0073
, tidak ada baris baru.a<space><space>b
menjadia<space>b
. 2. Bahkan lebih: itu akan berubaha"b"c'd'e
menjadiabcde
. 3. Bahkan lebih: itu akan gagala"b
, dll.Ada solusi yang hanya menggunakan Bash built-in yang disebut wildcard :
Inilah yang sama terbungkus dalam suatu fungsi:
Anda melewatkan string yang akan dipotong dalam bentuk yang dikutip. misalnya:
Satu hal yang menyenangkan tentang solusi ini adalah ia akan bekerja dengan semua shell yang sesuai dengan POSIX.
Referensi
sumber
s=" 1 2 3 "; echo \""${s%1 2 3 }"\"
akan memangkas segalanya dari akhir, mengembalikan yang terkemuka" "
. Subbing1 2 3
dengan[![:space:]]*
mengatakannya untuk "menemukan karakter non-spasi pertama, kemudian clobber dan semuanya setelah". Menggunakan%%
bukannya%
membuat operasi trim-dari-akhir serakah. Ini bersarang di trim-dari-awal non-serakah, sehingga efeknya, Anda trim" "
dari awal. Kemudian, tukar%, #, dan * untuk ruang akhir. Bam!/bin/sh
(hanya dengan/usr/xpg4/bin/sh
, tetapi ini bukan apa yang akan digunakan dengan skrip sh biasa).${var%%[![:space:]]*}
kata "hapus darivar
substring terpanjang yang dimulai dengan karakter non-spasi". Itu berarti Anda hanya dibiarkan dengan spasi terkemuka, yang selanjutnya Anda hapus${var#..
. Baris berikut (trailing) adalah kebalikannya.awk
,sed
,tr
,xargs
) hanya untuk spasi langsing dari satu string pada dasarnya gila - terutama ketika sebagian besar kerang (termasuk bash) sudah memberikan string yang asli fasilitas munging out-of-the-box.Bash memiliki fitur yang disebut ekspansi parameter , yang, antara lain, memungkinkan penggantian string berdasarkan apa yang disebut pola (pola menyerupai ekspresi reguler, tetapi ada perbedaan dan batasan mendasar). [Baris asli flussence: Bash memiliki ekspresi reguler, tetapi mereka tersembunyi dengan baik:]
Berikut ini menunjukkan cara menghapus semua ruang putih (bahkan dari interior) dari nilai variabel.
sumber
${var/ /}
menghapus karakter spasi pertama.${var// /}
menghapus semua karakter spasi. Tidak ada cara untuk memotong hanya memimpin dan mengikuti spasi dengan hanya konstruksi ini.Untuk menghapus semua spasi dari awal dan akhir string (termasuk karakter akhir baris):
Ini juga akan menghapus ruang duplikat:
Menghasilkan: 'string ini memiliki banyak ruang'
sumber
echo -n
?echo " my string " | xargs
memiliki output yang sama.Strip satu memimpin dan satu spasi tambahan
Sebagai contoh:
Keluaran:
Lepaskan semua ruang depan dan belakang
Sebagai contoh:
Keluaran:
sumber
'hello world ', 'foo bar', 'both sides '
Dari bagian Bash Guide tentang globbing
Untuk menggunakan extglob dalam ekspansi parameter
Berikut fungsi yang sama yang dibungkus dalam suatu fungsi (CATATAN: Perlu mengutip string input yang diteruskan ke fungsi):
Pemakaian:
Jika kita mengubah fungsi untuk dieksekusi dalam subkulit, kita tidak perlu khawatir tentang memeriksa opsi shell saat ini untuk extglob, kita bisa mengaturnya tanpa mempengaruhi shell saat ini. Ini sangat menyederhanakan fungsi. Saya juga memperbarui parameter posisi "di tempat" jadi saya bahkan tidak perlu variabel lokal
begitu:
sumber
extglob
, dengan menggunakanshopt -p
: cukup tulislocal restore="$(shopt -p extglob)" ; shopt -s extglob
di awal fungsi Anda, daneval "$restore"
di akhir (kecuali, memang, eval itu jahat ...).[[:space:]]
bisa diganti dengan, well, spasi:${var##+( )}
dan${var%%+( )}
berfungsi dengan baik dan lebih mudah dibaca.Anda dapat memotongnya hanya dengan
echo
:sumber
foo
berisi wildcard? misalnya,foo=" I * have a wild card"
... kejutan! Selain itu, ini runtuh beberapa ruang yang berdekatan menjadi satu.Saya selalu melakukannya dengan sed
Jika ada solusi yang lebih elegan, saya harap seseorang mempostingnya.
sumber
sed
?sed -e 's/\s*$//'
. Penjelasan: 's' berarti pencarian, '\ s' berarti semua spasi putih, '*' berarti nol atau banyak, '$' berarti sampai akhir baris dan '//' berarti mengganti semua kecocokan dengan string kosong .Anda dapat menghapus baris baru dengan
tr
:sumber
Dengan fitur pencocokan pola diperpanjang Bash diaktifkan (
shopt -s extglob
), Anda dapat menggunakan ini:{trimmed##*( )}
untuk menghapus jumlah ruang utama yang sewenang-wenang.
sumber
/bin/sh -o posix
bekerja juga, tetapi saya curiga.trimmed
? Apakah itu hal bawaan atau variabel yang sedang dipangkas?sumber
read
akan disimpan di variabel dengan namanya $ 1 versi yang dipangkas nilainya $ {! 1}trim() { while [[ $# -gt 0 ]]; do read -rd '' $1 <<<"${!1}"; shift; done; }
read -rd '' str <<<"$str"
lakukan.Ada banyak jawaban, tetapi saya masih percaya naskah saya yang baru saja ditulis layak disebutkan karena:
"$*"
gabungan beberapa argumen menggunakan satu spasi. jika Anda ingin memotong & hanya menampilkan argumen pertama, gunakan"$1"
sajaNaskah:
Pemakaian:
Keluaran:
sumber
[\ \t]
[[:space:]]
seperti di salah satu jawaban lain: stackoverflow.com/a/3352015/3968618Anda bisa menggunakan old-school
tr
. Sebagai contoh, ini mengembalikan jumlah file yang dimodifikasi dalam repositori git, spasi putih dilucuti.sumber
Ini bekerja untuk saya:
Untuk membuatnya lebih sedikit pada baris untuk hasil yang sama:
sumber
${var##Pattern}
untuk detail lebih lanjut. Juga, situs ini menjelaskan pola bash . Jadi##
cara menghapus pola yang diberikan dari depan dan%%
berarti menghapus pola yang diberikan dari belakang. The+( )
porsi pola dan itu berarti "satu atau lebih terjadinya ruang"ATAU
ATAU
ATAU
ATAU
Membangun di atas soulution exp ...
ATAU
sumber
Saya telah melihat skrip hanya menggunakan tugas variabel untuk melakukan pekerjaan:
Ruang kosong secara otomatis digabungkan dan dipangkas. Kita harus berhati-hati terhadap metakarakter shell (risiko injeksi potensial).
Saya juga merekomendasikan untuk selalu memberikan dua kali penggantian variabel dalam kondisi shell:
karena sesuatu seperti -o atau konten lain dalam variabel dapat mengubah argumen pengujian Anda.
sumber
$xyz
denganecho
yang melakukan penggabungan spasi, bukan variabel tugas. Untuk menyimpan nilai yang dipangkas dalam variabel dalam contoh Anda, Anda harus menggunakanxyz=$(echo -n $xyz)
. Juga, pendekatan ini tunduk pada ekspansi pathname yang mungkin tidak diinginkan (globbing).xyz
variabel TIDAK dipangkas.sumber
echo $(echo "1 2 3")
(dengan dua spasi antara 1, 2, dan 3).Saya hanya akan menggunakan sed:
a) Contoh penggunaan pada string baris tunggal
Keluaran:
b) Contoh penggunaan pada string multi-line
Keluaran:
c) Catatan akhir:
Jika Anda tidak suka menggunakan fungsi, untuk string baris tunggal Anda cukup menggunakan perintah "lebih mudah diingat" seperti:
Contoh:
Keluaran:
Menggunakan hal di atas pada string multi-line akan berfungsi juga , tetapi harap dicatat bahwa itu akan memotong semua ruang trailing / leading internal juga, seperti yang GuruM perhatikan dalam komentar
Keluaran:
Jadi, jika Anda berkeinginan untuk menjaga jarak tersebut, silakan gunakan fungsi ini di awal jawaban saya!
d) PENJELASAN sintaks sed "find and replace" pada string multi-line yang digunakan di dalam fungsi trim:
sumber
Inilah fungsi trim () yang memotong dan menormalkan spasi putih
Dan varian lain yang menggunakan ekspresi reguler.
sumber
*
karakter dalam string input akan perluas ke semua file dan folder di folder yang aktif saat ini. Akhirnya, jika $ IFS diatur ke nilai non-default, pemangkasan mungkin tidak berfungsi (meskipun mudah diperbaiki dengan menambahkanlocal IFS=$' \t\n'
). Pemotongan terbatas pada bentuk spasi putih berikut: spasi,\t
dan\n
karakter.if
sesuai dengan:if [[ "$trimmed" =~ ' '*([^ ]|[^ ].*[^ ])' '* ]]
. Akhirnya, pendekatan ini hanya berurusan dengan spasi, bukan bentuk spasi putih lainnya (lihat komentar saya selanjutnya).if
baris dengan:[[ "$trimmed" =~ [[:space:]]*([^[:space:]]|[^[:space:]].*[^[:space:]])[[:space:]]* ]]
Gunakan AWK:
sumber
$stripped_version=
gema $ var | awk '{gsub (/ ^ + | + $ /, "")} 1'``Tugas mengabaikan spasi putih terkemuka dan tertinggal dan karenanya dapat digunakan untuk memotong:
sumber
echo "$var"
untuk melihat nilai dengan spasi.var=$(echo $var)
tetapi saya tidak merekomendasikannya. Solusi lain yang disajikan di sini lebih disukai.Ini tidak memiliki masalah dengan globbing yang tidak diinginkan, juga, ruang putih interior tidak dimodifikasi (dengan asumsi yang
$IFS
diatur ke default, yaitu' \t\n'
).Itu membaca hingga baris baru pertama (dan tidak termasuk itu) atau akhir string, mana yang lebih dulu, dan menghapus setiap campuran ruang dan
\t
karakter memimpin dan tertinggal . Jika Anda ingin mempertahankan beberapa baris (dan juga menghapus dan memimpin baris baru), gunakanread -r -d '' var << eof
sebaliknya; Perhatikan, bagaimanapun, bahwa jika input Anda mengandung\neof
, itu akan dipotong sebelum. (Bentuk ruang putih lainnya, yaitu\r
,,\f
dan\v
, tidak dilucuti, bahkan jika Anda menambahkannya ke $ IFS.)sumber
Untuk menghapus spasi dan tab dari kiri ke kata pertama, masukkan:
cyberciti.biz/tips/delete-leading-spaces-from-front-of-each-word.html
sumber
Ini akan menghapus semua spasi putih dari String Anda,
/
menggantikan kemunculan pertama dan//
semua kemunculan spasi putih dalam string. Yaitu semua ruang putih bisa diganti dengan - tidak adasumber
Ini adalah metode paling sederhana yang pernah saya lihat. Hanya menggunakan Bash, hanya beberapa baris, regexp sederhana, dan cocok dengan semua bentuk spasi putih:
Berikut ini contoh skrip untuk mengujinya:
sumber
^[[:space:]]*(.*[^[:space:]])?[[:space:]]*$
Python memiliki fungsi
strip()
yang identik dengan PHPtrim()
, jadi kita bisa melakukan sedikit inline Python untuk membuat utilitas yang mudah dimengerti untuk ini:Ini akan memangkas spasi putih depan dan akhir (termasuk baris baru).
sumber
sumber
Saya menemukan bahwa saya perlu menambahkan beberapa kode dari
sdiff
keluaran yang berantakan untuk membersihkannya:Ini menghilangkan spasi tambahan dan karakter tak terlihat lainnya.
sumber
Menghapus spasi ke satu ruang:
sumber