Saya memiliki sebuah shell script dengan kode ini:
var=`hg st -R "$path"`
if [ -n "$var" ]; then
echo $var
fi
Tapi kode kondisional selalu mengeksekusi, karena hg st
selalu mencetak setidaknya satu karakter newline.
$var
(seperti trim()
di PHP)?atau
Saya bisa menggunakan sed atau AWK, tapi saya'd suka berpikir ada solusi yang lebih elegan untuk masalah ini.
Let's mendefinisikan sebuah variabel yang berisi terdepan, tertinggal, dan menengah spasi:
FOO=' test test test '
echo -e "FOO='${FOO}'"
# > FOO=' test test test '
echo -e "length(FOO)==${#FOO}"
# > length(FOO)==16
Bagaimana untuk menghapus semua spasi (dilambangkan dengan [:space:]
di tr
):
FOO=' test test test '
FOO_NO_WHITESPACE="$(echo -e "${FOO}" | tr -d '[:space:]')"
echo -e "FOO_NO_WHITESPACE='${FOO_NO_WHITESPACE}'"
# > FOO_NO_WHITESPACE='testtesttest'
echo -e "length(FOO_NO_WHITESPACE)==${#FOO_NO_WHITESPACE}"
# > length(FOO_NO_WHITESPACE)==12
Bagaimana untuk menghapus ruang kosong hanya:
FOO=' test test test '
FOO_NO_LEAD_SPACE="$(echo -e "${FOO}" | sed -e 's/^[[:space:]]*//')"
echo -e "FOO_NO_LEAD_SPACE='${FOO_NO_LEAD_SPACE}'"
# > FOO_NO_LEAD_SPACE='test test test '
echo -e "length(FOO_NO_LEAD_SPACE)==${#FOO_NO_LEAD_SPACE}"
# > length(FOO_NO_LEAD_SPACE)==15
Bagaimana untuk menghapus spasi yang tertinggal hanya:
FOO=' test test test '
FOO_NO_TRAIL_SPACE="$(echo -e "${FOO}" | sed -e 's/[[:space:]]*$//')"
echo -e "FOO_NO_TRAIL_SPACE='${FOO_NO_TRAIL_SPACE}'"
# > FOO_NO_TRAIL_SPACE=' test test test'
echo -e "length(FOO_NO_TRAIL_SPACE)==${#FOO_NO_TRAIL_SPACE}"
# > length(FOO_NO_TRAIL_SPACE)==15
Cara memindahkan investasi terkemuka dan trailing spasi--rantai `sed ini:
FOO=' test test test '
FOO_NO_EXTERNAL_SPACE="$(echo -e "${FOO}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')"
echo -e "FOO_NO_EXTERNAL_SPACE='${FOO_NO_EXTERNAL_SPACE}'"
# > FOO_NO_EXTERNAL_SPACE='test test test'
echo -e "length(FOO_NO_EXTERNAL_SPACE)==${#FOO_NO_EXTERNAL_SPACE}"
# > length(FOO_NO_EXTERNAL_SPACE)==14
Atau, jika anda bash mendukung itu, anda dapat mengganti echo -e "${FOO}" | sed ...
dengan sed ... <<<${FOO}
, seperti (untuk trailing whitespace):
FOO_NO_TRAIL_SPACE="$(sed -e 's/[[:space:]]*$//' <<<${FOO})"
Jawaban yang sederhana adalah:
echo " lol " | xargs
Xargs akan melakukan pemangkasan untuk anda. It's satu perintah/program, tidak ada parameter, kembali dipangkas string, semudah itu!
Catatan: ini doesn't menghapus ruang internal jadi "foo bar"
tetap sama. Hal itu TIDAK menjadi "foobar"
.
Ada solusi yang hanya menggunakan Bash built-in yang disebut wildcards:
var=" abc "
# remove leading whitespace characters
var="${var#"${var%%[![:space:]]*}"}"
# remove trailing whitespace characters
var="${var%"${var##*[![:space:]]}"}"
echo "===$var==="
Berikut ini's yang sama dibungkus dalam sebuah fungsi:
trim() {
local var="$*"
# remove leading whitespace characters
var="${var#"${var%%[![:space:]]*}"}"
# remove trailing whitespace characters
var="${var%"${var##*[![:space:]]}"}"
echo -n "$var"
}
Anda lulus string yang akan dipangkas dalam bentuk dikutip. misalnya:
trim " abc "
Hal yang baik tentang solusi ini adalah bahwa itu akan bekerja dengan POSIX-compliant shell.
Bash memiliki fitur yang disebut parameter ekspansi, yang, antara lain, memungkinkan string pengganti berdasarkan disebut pola (pola menyerupai ekspresi reguler, tetapi ada perbedaan mendasar dan keterbatasan). [flussence's asli line: Bash memiliki ekspresi reguler, tetapi mereka're tersembunyi:]
Berikut ini menunjukkan bagaimana untuk menghapus semua ruang putih (bahkan dari interior) dari suatu nilai variabel.
$ var='abc def'
$ echo "$var"
abc def
# Note: flussence's original expression was "${var/ /}", which only replaced the *first* space char., wherever it appeared.
$ echo -n "${var//[[:space:]]/}"
abcdef
Dalam rangka untuk menghapus semua spasi dari awal dan akhir string (termasuk karakter akhir baris):
echo $variable | xargs echo -n
Ini akan menghapus duplikat ruang juga:
echo " this string has a lot of spaces " | xargs echo -n
Menghasilkan: 'string ini memiliki banyak ruang'
trim()
{
local trimmed="$1"
# Strip leading space.
trimmed="${trimmed## }"
# Strip trailing space.
trimmed="${trimmed%% }"
echo "$trimmed"
}
Misalnya:
test1="$(trim " one leading")"
test2="$(trim "one trailing ")"
test3="$(trim " one leading and one trailing ")"
echo "'$test1', '$test2', '$test3'"
Output:
'one leading', 'one trailing', 'one leading and one trailing'
trim()
{
local trimmed="$1"
# Strip leading spaces.
while [[ $trimmed == ' '* ]]; do
trimmed="${trimmed## }"
done
# Strip trailing spaces.
while [[ $trimmed == *' ' ]]; do
trimmed="${trimmed%% }"
done
echo "$trimmed"
}
Misalnya:
test4="$(trim " two leading")"
test5="$(trim "two trailing ")"
test6="$(trim " two leading and two trailing ")"
echo "'$test4', '$test5', '$test6'"
Output:
'two leading', 'two trailing', 'two leading and two trailing'
Dari Bash Panduan bagian di globbing
Untuk menggunakan extglob dalam parameter ekspansi
#Turn on extended globbing
shopt -s extglob
#Trim leading and trailing whitespace from a variable
x=${x##+([[:space:]])}; x=${x%%+([[:space:]])}
#Turn off extended globbing
shopt -u extglob
Berikut ini's fungsi yang sama dengan dibungkus dalam sebuah fungsi (CATATAN: Perlu mengutip input string yang dilewatkan ke fungsi):
trim() {
# Determine if 'extglob' is currently on.
local extglobWasOff=1
shopt extglob >/dev/null && extglobWasOff=0
(( extglobWasOff )) && shopt -s extglob # Turn 'extglob' on, if currently turned off.
# Trim leading and trailing whitespace
local var=$1
var=${var##+([[:space:]])}
var=${var%%+([[:space:]])}
(( extglobWasOff )) && shopt -u extglob # If 'extglob' was off before, turn it back off.
echo -n "$var" # Output trimmed string.
}
Penggunaan:
string=" abc def ghi ";
#need to quote input-string to preserve internal white-space if any
trimmed=$(trim "$string");
echo "$trimmed";
Jika kita mengubah fungsi untuk mengeksekusi dalam suatu subkulit, kita don't perlu khawatir tentang pemeriksaan shell saat ini pilihan untuk extglob, kita hanya dapat diatur tanpa mempengaruhi shell saat ini. Ini menyederhanakan fungsi sangat. Saya juga memperbarui parameter posisi "tempat" jadi saya don't bahkan perlu variabel lokal
trim() {
shopt -s extglob
set -- "${1##+([[:space:]])}"
printf "%s" "${1%%+([[:space:]])}"
}
jadi:
$ s=$'\t\n \r\tfoo '
$ shopt -u extglob
$ shopt extglob
extglob off
$ printf ">%q<\n" "$s" "$(trim "$s")"
>$'\t\n \r\tfoo '<
>foo<
$ shopt extglob
extglob off
# Trim whitespace from both ends of specified parameter
trim () {
read -rd '' $1 <<<"${!1}"
}
# Unit test for trim()
test_trim () {
local foo="$1"
trim foo
test "$foo" = "$2"
}
test_trim hey hey &&
test_trim ' hey' hey &&
test_trim 'ho ' ho &&
test_trim 'hey ho' 'hey ho' &&
test_trim ' hey ho ' 'hey ho' &&
test_trim $'\n\n\t hey\n\t ho \t\n' $'hey\n\t ho' &&
test_trim $'\n' '' &&
test_trim '\n' '\n' &&
echo passed
Ada banyak jawaban, tapi aku masih percaya saya hanya-naskah yang ditulis adalah layak disebutkan karena:
"$*"
bergabung dengan beberapa argumen yang menggunakan satu ruang. jika anda ingin langsing & output hanya argumen pertama, gunakan "$1"
bukanScript:
trim() {
local s2 s="$*"
# note: the brackets in each of the following two lines contain one space
# and one tab
until s2="${s#[ ]}"; [ "$s2" = "$s" ]; do s="$s2"; done
until s2="${s%[ ]}"; [ "$s2" = "$s" ]; do s="$s2"; done
echo "$s"
}
Penggunaan:
mystring=" here is
something "
mystring=$(trim "$mystring")
echo ">$mystring<"
Output:
>here is
something<
Ini bekerja untuk saya:
text=" trim my edges "
trimmed=$text
trimmed=${trimmed##+( )} #Remove longest matching series of spaces from the front
trimmed=${trimmed%%+( )} #Remove longest matching series of spaces from the back
echo "<$trimmed>" #Adding angle braces just to make it easier to confirm that all spaces are removed
#Result
<trim my edges>
Untuk menempatkan bahwa pada lebih sedikit untuk hasil yang sama:
text=" trim my edges "
trimmed=${${text##+( )}%%+( )}
# Strip leading and trailing white space (new line inclusive).
trim(){
[[ "$1" =~ [^[:space:]](.*[^[:space:]])? ]]
printf "%s" "$BASH_REMATCH"
}
ATAU
# Strip leading white space (new line inclusive).
ltrim(){
[[ "$1" =~ [^[:space:]].* ]]
printf "%s" "$BASH_REMATCH"
}
# Strip trailing white space (new line inclusive).
rtrim(){
[[ "$1" =~ .*[^[:space:]] ]]
printf "%s" "$BASH_REMATCH"
}
# Strip leading and trailing white space (new line inclusive).
trim(){
printf "%s" "$(rtrim "$(ltrim "$1")")"
}
ATAU
# Strip leading and trailing specified characters. ex: str=$(trim "$str" $'\n a')
trim(){
if [ "$2" ]; then
trim_chrs="$2"
else
trim_chrs="[:space:]"
fi
[[ "$1" =~ ^["$trim_chrs"]*(.*[^"$trim_chrs"])["$trim_chrs"]*$ ]]
printf "%s" "${BASH_REMATCH[1]}"
}
ATAU
# Strip leading specified characters. ex: str=$(ltrim "$str" $'\n a')
ltrim(){
if [ "$2" ]; then
trim_chrs="$2"
else
trim_chrs="[:space:]"
fi
[[ "$1" =~ ^["$trim_chrs"]*(.*[^"$trim_chrs"]) ]]
printf "%s" "${BASH_REMATCH[1]}"
}
# Strip trailing specified characters. ex: str=$(rtrim "$str" $'\n a')
rtrim(){
if [ "$2" ]; then
trim_chrs="$2"
else
trim_chrs="[:space:]"
fi
[[ "$1" =~ ^(.*[^"$trim_chrs"])["$trim_chrs"]*$ ]]
printf "%s" "${BASH_REMATCH[1]}"
}
# Strip leading and trailing specified characters. ex: str=$(trim "$str" $'\n a')
trim(){
printf "%s" "$(rtrim "$(ltrim "$1" "$2")" "$2")"
}
ATAU
Bangunan atas moskit's expr soulution...
# Strip leading and trailing white space (new line inclusive).
trim(){
printf "%s" "`expr "$1" : "^[[:space:]]*\(.*[^[:space:]]\)[[:space:]]*$"`"
}
ATAU
# Strip leading white space (new line inclusive).
ltrim(){
printf "%s" "`expr "$1" : "^[[:space:]]*\(.*[^[:space:]]\)"`"
}
# Strip trailing white space (new line inclusive).
rtrim(){
printf "%s" "`expr "$1" : "^\(.*[^[:space:]]\)[[:space:]]*$"`"
}
# Strip leading and trailing white space (new line inclusive).
trim(){
printf "%s" "$(rtrim "$(ltrim "$1")")"
}
I've melihat script hanya menggunakan variabel penugasan untuk melakukan pekerjaan:
$ xyz=`echo -e 'foo \n bar'`
$ echo $xyz
foo bar
Spasi secara otomatis bersatu dan dipangkas. Satu harus berhati-hati dari shell metakarakter (potensi injeksi risiko).
Saya juga akan merekomendasikan selalu double-mengutip variabel substitusi dalam shell conditional:
if [ -n "$var" ]; then
karena sesuatu seperti -o atau konten lainnya pada variabel yang bisa mengubah anda menguji argumen.
Saya hanya akan menggunakan sed:
function trim
{
echo "$1" | sed -n '1h;1!H;${;g;s/^[ \t]*//g;s/[ \t]*$//g;p;}'
}
a) Contoh penggunaan single-line string
string=' wordA wordB wordC wordD '
trimmed=$( trim "$string" )
echo "GIVEN STRING: |$string|"
echo "TRIMMED STRING: |$trimmed|"
Output:
GIVEN STRING: | wordA wordB wordC wordD |
TRIMMED STRING: |wordA wordB wordC wordD|
b) Contoh penggunaan multi-line string
string=' wordA
>wordB<
wordC '
trimmed=$( trim "$string" )
echo -e "GIVEN STRING: |$string|\n"
echo "TRIMMED STRING: |$trimmed|"
Output:
GIVEN STRING: | wordAA
>wordB<
wordC |
TRIMMED STRING: |wordAA
>wordB<
wordC|
c) catatan Akhir:
Jika anda don't ingin menggunakan fungsi, untuk single-line string anda hanya dapat menggunakan "lebih mudah untuk diingat" perintah seperti:
echo "$string" | sed -e 's/^[ \t]*//' | sed -e 's/[ \t]*$//'
Contoh:
echo " wordA wordB wordC " | sed -e 's/^[ \t]*//' | sed -e 's/[ \t]*$//'
Output:
wordA wordB wordC
Menggunakan kode di atas pada multi-line string akan bekerja dengan baik, tetapi harap dicatat bahwa itu akan memotong setiap tertinggal/terkemuka internal beberapa ruang, seperti GuruM melihat di komentar
string=' wordAA
>four spaces before<
>one space before< '
echo "$string" | sed -e 's/^[ \t]*//' | sed -e 's/[ \t]*$//'
Output:
wordAA
>four spaces before<
>one space before<
Jadi, jika anda keberatan untuk menjaga ruang tersebut, silakan gunakan fungsi pada awal jawaban saya!
d) PENJELASAN sed sintaks "cari dan ganti" pada multi-line string yang digunakan di dalam fungsi trim:
sed -n '
# If the first line, copy the pattern to the hold buffer
1h
# If not the first line, then append the pattern to the hold buffer
1!H
# If the last line then ...
$ {
# Copy from the hold to the pattern buffer
g
# Do the search and replace
s/^[ \t]*//g
s/[ \t]*$//g
# print
p
}'
Berikut ini's trim() fungsi trim dan menormalkan spasi
#!/bin/bash
function trim {
echo $*
}
echo "'$(trim " one two three ")'"
# 'one two three'
Dan varian lain yang menggunakan ekspresi reguler.
#!/bin/bash
function trim {
local trimmed="$@"
if [[ "$trimmed" =~ " *([^ ].*[^ ]) *" ]]
then
trimmed=${BASH_REMATCH[1]}
fi
echo "$trimmed"
}
echo "'$(trim " one two three ")'"
# 'one two three'