Bir dizenin yeni satır karakterine sahip olduğu ve varsa silindiği nasıl iddia edilir


9

Üzerinde hiçbir kontrol var bazı işlem sonucu bir dize var. Bu değişkeni kullanarak yazdırdığımda echoşunu elde ederim:

echo $myvar
hello

Ancak, yaptığımda

if [ $myvar = "hello" ]; then
    echo they are equal
else
    echo they are not equal
fi

Her zaman eşit olmadıklarını anlıyorum. Bunun bir newlinekarakter yüzünden olduğundan şüpheleniyorum .

Dize ayrıca garip davranır. Ben yaparken:

newVAR="this is my var twice: "$myvar$myvar
echo $newVAR

Alırım:

hellois my var twice: hello

Bunun aslında bir a nedeniyle olup olmadığını nasıl kontrol edebilirim newlineve eğer öyleyse kaldırın?


1
Bash'te printf '%q\n' "$string"herhangi bir dizenin kaçan bir sürümünü alabilirsiniz. Örneğin: printf '%q\n' 'foo\n'-> foo\\n; printf '%q\n' $'foo\n'->$'foo\n'
l0b0

1
Değişkenlerinizin herhangi birinin genişlemesini teklif etmiyorsunuz. Sondaki boşlukları olsaydı, onu göremezdiniz echo $foo. Bunun echo "$foo"yerine yapın.
Peter Cordes

Yanıtlar:


9

Sorun, gömülü bir Satır Başı (CR, \r) olması. Bu, terminal metni ekleme noktasının yazdırdığı satırın başına geri dönmesine neden olur. Bu nedenle, $newVARörneğinizdeki satırın başında 'merhaba' görüyorsunuz - sed -n lyazdırılamayan karakterlerin (ve satır sonunun) okunabilir bir görünümünü görüntüler.

var=ab$'\r'c ; echo "$var";  printf %s "$var" | sed -n l
# output:
cb
ab\rc$

Basit bir bash durum kontrolü ile test edebilirsiniz:

[[ $var == *$'\r'* ]] && echo yes || echo no
# output:
yes

Testi ve düzeltmeyi, aşağıdakileri test \rederek ve kaldırarak tek adımda birleştirebilirsiniz :

fix="${var//$'\r'/}"; echo "$var"; echo "$fix"
# output:
cb
abc

Düzeltme kullanan Kabuk Parametrelerinin . Yukarıda kullanılan özel form, önerilen dizginize göre alt dizeleri değiştirmek içindir: ${parameter/pattern/string}<- Bu yalnızca, bulunan ilk kalıbı * parametresi adlı değişkende dize ile değiştirir . Değiştirmek için tüm desenleri, sadece ilk değiştirmeniz gerekir /için //.


son kod parçanızı açıklayabilir misiniz? fix="....hat?
farid99

@ farid99: cevaba açıklama eklendi, Not kendisi fixolabilir var- veya genellikle (muhtemelen) değiştirilmiş değeri yeniden atamaya gerek kalmadan parametre genişlemesini olduğu gibi kullanabilirsiniz ..
Peter.O

5

Bash'da \rolduğu gibi temsil edebilirsiniz $'\r':

if [ "$myvar" = "hello"$'\r' ]; then
    echo they are equal
else
    echo they are not equal
fi

Veya son doğramak \rin myvar:

if [ "${myvar%$'\r'*}" = "hello" ]; then
    echo they are equal
else
    echo they are not equal
fi

3

Merakla, birçok mermide getoptsböyle bir iş için çok muhtemel bir aday. Bu başlangıçta mantıksız görünebilir, ancak getopts'birincil işlev, birleştirilmiş bir dizi dizide bulunabilecek kadar çok sayıda tek karakter komut satırı seçeneği tanımak ve yorumlamak için teklif edilirse , biraz yapmaya başlayabilir daha mantıklı.

Bir bashkabuktan göstermek için :

x=$(printf '\n\r%010s\t' hello)
OPTIND=1
while  getopts : na "-$x"
do     printf %q\\n "$OPTARG"
done

$'\n'
$'\r'
\
\
\
\
\
h
e
l
l
o
$'\t'

Bu şekilde, bu gibi durumlar getoptsiçin sökme işleminin bir tür kabuk otomatik pilotu olarak ele alınmasına izin vermek bazen uygun olabilir . Bunu yaptığınızda, istenmeyen baytları w / a ile görüntüleyebilir caseveya dize yedeklemenizi bayt 1'den [test edebilir ]ve oluşturabilirsiniz:

OPTIND=1 y=$(printf \\n\\r) z=
while  getopts : na "-$x"
do     case $OPTARG in ([!$y])
            z=$z$OPTARG
       esac
done
printf %q\\n "$z"

$'     hello\t'

Bu basit örnek durum göz önüne alındığında - ve daha önce bahsedilen başka bir yerde parametre genişletmelerini destekleyen bir kabuk verildiğinde - bahsedilen genişletmeler muhtemelen size daha iyi hizmet edecektir. Ancak getopts, bu konudaki yeteneklerinin farkında olmasanız da söz etmeye değer olabileceğini düşündüm . Kesinlikle öğrendiğimde, bunun için birçok yararlı uygulama buldum.


0

Bash ve diğer kabuk dilleri kullanışlı olsa da, bazen Perl gibi gerçek bir komut dosyası dili kullanmak daha iyidir. Perl, sed ve awk gibi diğer dilleri ve UNIX komutlarını çağıran kabuk komut dosyalarının yerini kolayca alabilir. Bunu 20+ yıl önce, FORTRAN kodunu aramadan önce sed, awk ve çeşitli UNIX komutları olarak adlandırılan C-Shell betikleri yazarken öğrendim. Perl'de yapardım:

chomp($myvar);   # removes the newline char

if("$myvar" eq "hello")   # string comparison
  {
  print "they are equal\n";
  }
else
  {
  print "they are not equal\n";
  }
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.