bash: किसी वैरिएबल की पहली लाइन को वेरिएबल में असाइन करना


11

मेरे पास एक बहुस्तरीय चर है, और मैं केवल उस चर में पहली पंक्ति चाहता हूं। निम्न स्क्रिप्ट समस्या प्रदर्शित करता है:

#!/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

प्रश्न: कमांड के ${STRINGTEST%%$'\n'*}बाद रखे जाने पर पहली पंक्ति क्यों echoलौटती है, लेकिन असाइनमेंट के बाद रिक्त स्थान के साथ नई लाइनों को प्रतिस्थापित करें?


1
इसे पुन: पेश नहीं कर सकता। यह मेरे लिए उम्मीद के मुताबिक काम करता है।
पीक

1
2.05b, 3.1, 3.2, 4.0, 4.1, 4.2, 4.3 में से किसी के साथ पुन: पेश नहीं किया जा सकता है। एक उपयोगकर्ता त्रुटि की तरह लगता है जैसे इसे एक शेल के साथ चलाने की कोशिश करना $'...'जो बैश के बजाय समर्थन नहीं करता है ।
स्टीफन चेज़लस

जवाबों:


8

हो सकता है कि आप जो करना चाहते हैं उसे संग्रहीत करने का एक और तरीका है, लेकिन यह काम करता है

#!/bin/bash

STRINGTEST="
Onlygetthefirstline
butnotthesecond
orthethird
"

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

यह मानता है कि पंक्तियों में $STRINGTESTरिक्त स्थान या वाइल्डकार्ड नहीं हैं। यह भी ध्यान दें कि खाली लाइनों (उस चर में पहली पंक्ति के रूप में) को नजरअंदाज किया जाता है।
स्टीफन चेज़लस

3
यह भी ध्यान दें कि उपयोग करना STRINGTEST=(${STRINGTEST[@]})थोड़ा समझ में आता है और इसके बराबर है STRINGTEST=($STRINGTEST)क्योंकि STRINGTESTपहले इसे स्केलर ( सरणी नहीं ) चर के रूप में परिभाषित किया गया था ।
स्टीफन चेज़लस

10

सबसे कुशल नहीं हो सकता है लेकिन एक लाइनर ...

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

2
मुझे यह स्पष्टता और संक्षिप्तता के लिए पसंद है।
पीटर - मोनिका

यह firstLine=`echo "${test_var}" | sed -n 1pभी अगर आप के बजाय sed उपयोग करने के लिए कोई कारण है, काम करता है (उदाहरण के लिए, इसका मतलब है आप एक साथ लाइन के लिए एक स्थानापन्न के प्रदर्शन कर सकते हैं: echo "${test_var}" | sed -nE '1 s/# *(.*)/\1/p'
robenkleene

7

वह कोड मेरे लिए सभी संस्करणों के साथ काम करता है जिसे मैंने 2.05b और 4.3 के बीच आजमाया था। अधिक संभावना है कि आपने उस स्क्रिप्ट को एक अलग शेल के साथ चलाने की कोशिश की जो $'...'उद्धृत करने के रूप का समर्थन नहीं करता है ।

यही कारण है कि $'...'वाक्य रचना मानक नहीं है shवाक्य रचना (अभी तक) और केवल (2015/05/22 और AFAIK के रूप में) समर्थित द्वारा ksh93(जहाँ से यह जन्म), zsh, bash, के हाल के संस्करणों mkshऔर shFreeBSD के या हाल के संस्करण

मेरे शर्त होगी आप के साथ है कि स्क्रिप्ट चलाने के लिए करने की कोशिश की है कि shबजाय bashऔर अपने shसंस्करणों पर आधारित है ash, pdksh, yashया ksh88कि यह अभी तक का समर्थन नहीं करते।

यदि आप उस कोड POSIX 2008 को संगत बनाना चाहते हैं, तो आपको इसे लिखना होगा:

STRINGTEST="Onlygetthefirstline
butnotthesecond
orthethird"

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

फिर, आप इसे किसी भी POSIX आज्ञाकारी खोल की तरह bashया अपने जैसे किसी झुकाव वाले / तेज लोगों द्वारा व्याख्या कर सकते हैं sh

(और याद रखें कि सूची के संदर्भ में एक चर को छोड़ना बॉर्न-जैसे गोले में एक बहुत ही विशेष अर्थ है)।


या यह बैश का एक पुराना संस्करण हो सकता है। मैं 2.03 के साथ व्यवहार को पुन: पेश कर सकता हूं।
गाइल्स का SO- बुराई पर रोक '22

@ गाइल्स, आखिरी समर्थित ओएस जिसमें बैश-2.03 (16 साल पहले जारी) शामिल था, शायद सोलारिस 8 था जो 3 साल पहले ईओएल पर चला गया था। यह परिकल्पना काफी संभावना नहीं है।
स्टीफन चेज़लस

1

यह मेरे लिए काम करता है:

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

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

और यह रिक्त लाइनों के लिए भी काम करता है:

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

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

यदि एक प्रक्रिया प्रतिस्थापन में आग लगने से परेशान व्यक्ति एक readबार एक साधारण चर ( readarrayप्लस इंडेक्सिंग के बजाय ) में बस एक बार आग लगा सकता है ।
पीटर - मोनिका

0

बैश के साथ बिल्ट-इन readऔर यहाँ-स्ट्रिंग:

#!/usr/bin/env bash

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


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

POSIX मापदंडों के विस्तार का उपयोग:

#!/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"
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.