bash: Bir değişkenin ilk satırını bir değişkene atama


11

Çok satırlı bir değişkenim var ve yalnızca bu değişkenin ilk satırını istiyorum. Aşağıdaki komut dosyası sorunu gösterir:

#!/bin/bash

STRINGTEST="Onlygetthefirstline
butnotthesecond
orthethird"

echo "  Take the first line and send to standard output:"
echo ${STRINGTEST%%$'\n'*}
#   Output is as follows:
# Onlygetthefirstline

echo "  Set the value of the variable to the first line of the variable:"
STRINGTEST=${STRINGTEST%%$'\n'*}

echo "  Send the modified variable to standard output:"
echo $STRINGTEST
#   Output is as follows:
# Onlygetthefirstline butnotthesecond orthethird

Soru: ${STRINGTEST%%$'\n'*}Komuttan sonra yerleştirildiğinde neden ilk satırı echodöndürüyor, ancak atamadan sonra satırları boşlukla değiştiriyor?


1
Yeniden üretilemiyor. Beklendiği gibi benim için çalışıyor.
Peque

1
2.05b, 3.1, 3.2, 4.0, 4.1, 4.2, 4.3 sürümlerinden hiçbiriyle çoğaltılamaz. $'...'Bash yerine desteklemeyen bir kabukla çalıştırmaya çalışmak gibi bir kullanıcı hatası gibi görünüyor .
Stéphane Chazelas

Yanıtlar:


8

Belki yapmak istediğiniz şeyi arşivlemenin başka bir yolu var, ama bu işe yarıyor

#!/bin/bash

STRINGTEST="
Onlygetthefirstline
butnotthesecond
orthethird
"

STRINGTEST=(${STRINGTEST[@]})
echo "${STRINGTEST[0]}"

Bu, satırların $STRINGTESTboşluk veya joker karakter içermediğini varsayar . Ayrıca boş satırların (bu değişkenin ilk satırında olduğu gibi) yoksayıldığını unutmayın.
Stéphane Chazelas

3
Ayrıca kullanarak not STRINGTEST=(${STRINGTEST[@]})önem taşımamaktadır ve eşdeğerdir STRINGTEST=($STRINGTEST)çünkü STRINGTESTdaha önce olarak tanımlandı skalar (değil dizi ) değişken.
Stéphane Chazelas

10

en verimli olmayabilir ama bir astar ...

firstLine=`echo "${multiLineVariable}" | head -1`

2
Açıklık ve kısalık için beğendim.
Peter - Monica'yı eski

Bu firstLine=`echo "${test_var}" | sed -n 1p: Bunun yerine sed kullanmak için bir neden varsa da çalışır (örneğin, o anda hattına yenisini yapabilmesi echo "${test_var}" | sed -nE '1 s/# *(.*)/\1/p'.
robenkleene

7

Bu kod benim için 2.05b ve 4.3 arasında denedim bash tüm sürümleri ile çalışır. Büyük olasılıkla bu komut dosyasını $'...'alıntı biçimini desteklemeyen farklı bir kabukla çalıştırmayı denediniz .

Bu $'...'sözdizimi standart değil shtarafından (henüz) sözdizimi ve tek (2015-05-22 ve afaik itibarıyla) desteklenen ksh93(o kökenli), zsh, bash, son versiyonları mkshve shFreeBSD veya son sürümlerini .

Bahse girerim o komut dosyasını çalıştırmak çalıştı olacağını shyerine bashve sizin shsürümleri dayanmaktadır ash, pdksh, yashveya ksh88bu kadar henüz desteklememektedir.

Bu kodu POSIX 2008 ile uyumlu hale getirmek istiyorsanız, şunu yazmanız gerekir:

STRINGTEST="Onlygetthefirstline
butnotthesecond
orthethird"

NL='
'
STRINGTEST=${STRINGTEST%%"$NL"*}
printf '%s\n' "$STRINGTEST"

Ardından, POSIX uyumlu herhangi bir kabuk bashveya sizin gibi daha yalın / daha hızlı olanlar tarafından yorumlanmasını sağlayabilirsiniz sh.

(ve bir değişkenin liste bağlamında ayrılmamasının Bourne benzeri mermilerde çok özel bir anlamı olduğunu unutmayın).


Veya bash'ın daha eski bir sürümü olabilir. Davranışı 2.03 ile çoğaltabilirim.
Gilles 'SO- kötü olmayı bırak'

@Gilles, bash-2.03'ü (16 yıl önce piyasaya sürüldü) içeren son desteklenen işletim sistemi muhtemelen 3 yıl önce EOL'ye giren Solaris 8 idi. Bu hipotez pek olası görünmüyor.
Stéphane Chazelas

1

Bu benim için çalışıyor:

STRINGTEST="Some Text 1
Some Text 2
Some Text 3"

readarray -t lines < <(echo "$STRINGTEST")
echo "${lines[0]}"

Ayrıca boş satırlar için de çalışır:

STRINGTEST="
Some Text 1
Some Text 2
Some Text 3"

readarray -t lines < <(echo "$STRINGTEST")
echo "${lines[0]}"

Eğer bir kişi süreç ikamesini ateşlemeye zorlarsa, readbasit bir değişkeni ( readarrayartı indeksleme yerine ) basitçe bir kez de yapabilir .
Peter - Monica'yı eski

0

Bash yerleşik readve burada-string ile:

#!/usr/bin/env bash

STRINGTEST="
Some Text 1
Some Text 2
Some Text 3"


IFS=$'\n' read -r STRINGTEST <<<"$STRINGTEST"

POSIX parametreleri genişletmeyi kullanma:

#!/usr/bin/env sh

STRINGTEST="
Some Text 1
Some Text 2
Some Text 3"

# Disables globing
set -f

# Field separator is newline only
IFS="
"

# No quotes, split lines as arguments because of IFS
set -- $STRINGTEST

# First argument is first line
STRINGTEST="$1"
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.