मैं कैसे एक स्ट्रिंग में एक newline sh में हो सकता है?


339

इस

STR="Hello\nWorld"
echo $STR

उत्पादन के रूप में उत्पादन करता है

Hello\nWorld

के बजाय

Hello
World

मुझे एक स्ट्रिंग में एक नई रेखा के लिए क्या करना चाहिए?

नोट: यह प्रश्न इको के बारे में नहीं है । मैं इसके बारे में जानता हूं echo -e, लेकिन मैं एक ऐसे समाधान की तलाश कर रहा हूं, जो अन्य आदेशों के तर्क के रूप में एक स्ट्रिंग (जिसमें एक नई पंक्ति भी शामिल है) को पारित करने की अनुमति देता है, जिसमें नई रूपरेखाओं की व्याख्या करने के लिए एक समान विकल्प न हो \n

जवाबों:


353

$'string'उदाहरण के लिए समाधान का उपयोग करना है :

$ STR=$'Hello\nWorld'
$ echo "$STR" # quotes are required here!
Hello
World

यहाँ बैश मैनुअल पेज से एक अंश है:

   Words of the form $'string' are treated specially.  The word expands to
   string, with backslash-escaped characters replaced as specified by  the
   ANSI  C  standard.  Backslash escape sequences, if present, are decoded
   as follows:
          \a     alert (bell)
          \b     backspace
          \e
          \E     an escape character
          \f     form feed
          \n     new line
          \r     carriage return
          \t     horizontal tab
          \v     vertical tab
          \\     backslash
          \'     single quote
          \"     double quote
          \nnn   the eight-bit character whose value is  the  octal  value
                 nnn (one to three digits)
          \xHH   the  eight-bit  character  whose value is the hexadecimal
                 value HH (one or two hex digits)
          \cx    a control-x character

   The expanded result is single-quoted, as if the  dollar  sign  had  not
   been present.

   A double-quoted string preceded by a dollar sign ($"string") will cause
   the string to be translated according to the current  locale.   If  the
   current  locale  is  C  or  POSIX,  the dollar sign is ignored.  If the
   string is translated and replaced, the replacement is double-quoted.

74
यह मान्य बैश है, लेकिन पॉसिंक श नहीं।
jmanning2k

7
+ 1-बस एक ध्यान दें: निर्यात varDynamic = "$ varAnother1 $ varAnother2" $ '\ n'
योर्डन जॉर्जियेव

3
यह वास्तव में ओपी द्वारा पूछे गए शाब्दिक तार के साथ काम करता है, लेकिन जैसे ही चर को प्रतिस्थापित किया जाता है, विफल हो जाता है: STR=$"Hello\nWorld"बस प्रिंट Hello\nWorld
ssc

3
@ssc सिंगल कोट्स, डबल नहीं
miken32

7
@ आपके उदाहरण में कोई चर नहीं हैं। साथ ही, इस विधि के लिए सिंगल कोट्स की आवश्यकता होती है। अंत में, प्रक्षेपित चर को शामिल करने के लिए आपको दोहरे-उद्धृत और विशेष-एकल-उद्धृत स्ट्रिंग को एक साथ जोड़ना होगा। उदाहरण के लिए H="Hello"; W="World"; STR="${H}"$'\n'"${W}"; echo "${STR}"अलग-अलग तर्ज पर "हैलो" और "वर्ल्ड" की प्रतिध्वनि होगी
JDS

166

इको इतनी नब्बे के दशक और खतरों से भरा है कि इसका उपयोग कोर डंप में परिणाम 4GB से कम नहीं होना चाहिए। गंभीर रूप से, गूंज की समस्याएं यही कारण थीं कि यूनिक्स मानकीकरण प्रक्रिया ने आखिरकार आविष्कार क्यों कियाprintf सभी समस्याओं को दूर उपयोगिता का ।

तो एक स्ट्रिंग में एक नई रेखा पाने के लिए:

FOO="hello
world"
BAR=$(printf "hello\nworld\n") # Alternative; note: final newline is deleted
printf '<%s>\n' "$FOO"
printf '<%s>\n' "$BAR"

वहाँ! कोई SYSV बनाम BSD इको पागलपन, सब कुछ बड़े करीने से मुद्रित हो जाता है और सी एस्केप अनुक्रमों के लिए पूरी तरह से पोर्टेबल समर्थन। हर कोई printfअब उपयोग करें और कभी पीछे मुड़कर न देखें।


3
इस उत्तर के लिए धन्यवाद, मुझे लगता है कि यह वास्तव में अच्छी सलाह प्रदान करता है। ध्यान दें, हालांकि, मेरा मूल प्रश्न वास्तव में कैसे था कि कैसे हम नए सिरे से प्रिंट करने के लिए प्रतिध्वनि प्राप्त करें, लेकिन एक शेल चर में एक नई पंक्ति कैसे प्राप्त करें। आप यह दिखाते हैं कि प्रिंटफ का उपयोग कैसे किया जाए, लेकिन मुझे लगता है कि एम्फ़ैटेमाचिन के उपयोग से समाधान और $'string'भी साफ है।
जुआन ए। नवारो

11
केवल 'स्वच्छ' की कमी वाली परिभाषा के लिए। $'foo'वाक्य रचना 2013 कई गोले शिकायत की के रूप में मान्य POSIX सिंटैक्स नहीं है।
जेन्स

5
BAR=$(printf "hello\nworld\n")मेरे लिए ट्रेलिंग \ n प्रिंट नहीं करता है
जॉनी

3
@ जॉनी इसे नहीं करना चाहिए; कमांड प्रतिस्थापन के लिए शेल स्पेसिफिकेशन कहता है कि आउटपुट के अंत में एक या अधिक newlines हटाए जाते हैं। मुझे लगता है कि यह मेरे उदाहरण के लिए अप्रत्याशित है और इसे प्रिंट में एक नई पंक्ति को शामिल करने के लिए संपादित किया है।
जेन्स

5
@ismael नहीं, $()POSIX द्वारा प्रतिस्थापन के अंत में एक या अधिक <newline> वर्णों के दृश्यों को हटाने के रूप में निर्दिष्ट किया गया है
जेन्स

61

मैंने अन्य उत्तरों के आधार पर जो किया वह था

NEWLINE=$'\n'
my_var="__between eggs and bacon__"
echo "spam${NEWLINE}eggs${my_var}bacon${NEWLINE}knight"

# which outputs:
spam
eggs__between eggs and bacon__bacon
knight

30

समस्या शेल के साथ नहीं है। समस्या वास्तव में echoकमांड के साथ ही है, और चर प्रक्षेप के आसपास दोहरे उद्धरण चिह्नों की कमी है। आप उपयोग करने का प्रयास कर सकते हैं echo -eलेकिन यह सभी प्लेटफार्मों पर समर्थित नहीं है, और इसका एक कारण हैprintf अब पोर्टेबिलिटी के लिए अनुशंसित है।

आप अपने शेल स्क्रिप्ट में सीधे नई पंक्ति सम्मिलित कर सकते हैं और सम्मिलित कर सकते हैं (यदि कोई स्क्रिप्ट वह है जो आप लिख रहे हैं) तो ऐसा दिखता है ...

#!/bin/sh
echo "Hello
World"
#EOF

या समकक्ष

#!/bin/sh
string="Hello
World"
echo "$string"  # note double quotes!

24

मैं -eध्वज को सुरुचिपूर्ण और सीधे आगे पाता हूं

bash$ STR="Hello\nWorld"

bash$ echo -e $STR
Hello
World

यदि स्ट्रिंग किसी अन्य कमांड का आउटपुट है, तो मैं बस उद्धरणों का उपयोग करता हूं

indexes_diff=$(git diff index.yaml)
echo "$indexes_diff"

2
यह अन्य उत्तरों में पहले ही उल्लेख किया जा चुका है। इसके अलावा, हालांकि यह पहले से ही था, मैंने इस तथ्य पर जोर देने के लिए प्रश्न को संपादित किया है कि यह प्रश्न नहीं है echo
जुआन ए। नवारो

यह सवाल का जवाब नहीं है
रोहित गुप्ता

यह पूरी तरह से उस सवाल का जवाब देता है जिसकी मुझे तलाश थी! धन्यवाद!
किवेलि

1
यहां मेरे लिए अच्छा काम किया। मैंने इस प्रतिध्वनि के आधार पर एक फ़ाइल बनाने के लिए उपयोग किया है और इसने आउटपुट पर नई लाइनें सही ढंग से उत्पन्न की हैं।
माटस लियोन

echo -eअपनी पोर्टेबिलिटी के मुद्दों के लिए कुख्यात है। यह प्री-पोसिक्स की तुलना में अब वाइल्ड वेस्ट की स्थिति से कम है, लेकिन पसंद करने के लिए अभी भी कोई कारण नहीं है echo -e। यह भी देखें stackoverflow.com/questions/11530203/…
tripleee

21
  1. एकमात्र सरल विकल्प वास्तव में चर में एक नई पंक्ति टाइप करना है:

    $ STR='new
    line'
    $ printf '%s' "$STR"
    new
    line

    हां, इसका मतलब है कि Enterकोड में जहां आवश्यक हो लेखन ।

  2. एक new lineचरित्र के कई समतुल्य हैं ।

    \n           ### A common way to represent a new line character.
    \012         ### Octal value of a new line character.
    \x0A         ### Hexadecimal value of a new line character.

    लेकिन उन सभी को कुछ टूल ( POSIX प्रिंटफ ) द्वारा "एक व्याख्या" की आवश्यकता होती है :

    echo -e "new\nline"           ### on POSIX echo, `-e` is not required.
    printf 'new\nline'            ### Understood by POSIX printf.
    printf 'new\012line'          ### Valid in POSIX printf.
    printf 'new\x0Aline'       
    printf '%b' 'new\0012line'    ### Valid in POSIX printf.

    और इसलिए, एक नई लाइन के साथ एक स्ट्रिंग बनाने के लिए उपकरण की आवश्यकता होती है:

    $ STR="$(printf 'new\nline')"
    $ printf '%s' "$STR"
    new
    line
  3. कुछ गोले में, अनुक्रम $'एक विशेष शैल विस्तार है। Ksh93, bash और zsh में काम करने के लिए जाना जाता है:

    $ STR=$'new\nline'
  4. बेशक, अधिक जटिल समाधान भी संभव हैं:

    $ echo '6e65770a6c696e650a' | xxd -p -r
    new
    line

    या

    $ echo "new line" | sed 's/ \+/\n/g'
    new
    line

6

एकल उद्धरण चिह्नों से पहले $ $ '... \ n ...' निम्नानुसार है, हालांकि दोहरे उद्धरण चिह्न काम नहीं करते हैं।

$ echo $'Hello\nWorld'
Hello
World
$ echo $"Hello\nWorld"
Hello\nWorld

4

मैं कोई बैश विशेषज्ञ नहीं हूं, लेकिन यह मेरे लिए काम करता है:

STR1="Hello"
STR2="World"
NEWSTR=$(cat << EOF
$STR1

$STR2
EOF
)
echo "$NEWSTR"

मुझे ग्रंथों को प्रारूपित करने में यह आसान लगा।


2
अच्छा पुराना वंशानुगत । और यह शायद POSIX शिकायत भी है!
15:24 बजे pyb

उद्धरण के आसपास $NEWSTRमें echo "$NEWSTR"यहां महत्वपूर्ण हैं
shadi

0

मेरे सिस्टम पर (Ubuntu 17.10) आपका उदाहरण वांछित के रूप में काम करता है, दोनों जब कमांड लाइन (टाइप) से टाइप किया जाता है shऔर जब shस्क्रिप्ट के रूप में निष्पादित होता है :

[bash sh
$ STR="Hello\nWorld"
$ echo $STR
Hello
World
$ exit
[bash echo "STR=\"Hello\nWorld\"
> echo \$STR" > test-str.sh
[bash cat test-str.sh 
STR="Hello\nWorld"
echo $STR
[bash sh test-str.sh 
Hello
World

मुझे लगता है कि यह आपके सवाल का जवाब देता है: यह सिर्फ काम करता है। (मैंने विवरणों का पता लगाने की कोशिश नहीं की है कि किस क्षण न्यूलाइन चरित्र का प्रतिस्थापन \nहोता है sh)।

हालाँकि, मैंने देखा कि यह एक ही स्क्रिप्ट के साथbash निष्पादित होने पर अलग तरह से व्यवहार करेगा और Hello\nWorldइसके बजाय प्रिंट आउट करेगा :

[bash bash test-str.sh
Hello\nWorld

मैं bashनिम्नानुसार वांछित आउटपुट प्राप्त करने में कामयाब रहा :

[bash STR="Hello
> World"
[bash echo "$STR"

चारों ओर दोहरे उद्धरणों पर ध्यान दें $STR। यदि यह bashस्क्रिप्ट के रूप में सहेजा और चलाया जाता है, तो यह व्यावहारिक रूप से व्यवहार करता है ।

निम्नलिखित भी वांछित उत्पादन देता है:

[bash echo "Hello
> World"

0

उन picky वाले जिन्हें सिर्फ नईलाइन की जरूरत है और इंडेंटेशन को तोड़ने वाले बहुस्तरीय कोड का तिरस्कार कर सकते हैं, वे कर सकते हैं:

IFS="$(printf '\nx')"
IFS="${IFS%x}"

बैश (और संभावित रूप से अन्य गोले) कमांड प्रतिस्थापन के बाद सभी अनुगामी न्यूलाइन्स को टटोलते हैं, इसलिए आपको printfएक नॉन-न्यूलाइन कैरेक्टर के साथ स्ट्रिंग को समाप्त करने और बाद में इसे हटाने की आवश्यकता है। यह भी आसानी से एक oneliner बन सकता है।

IFS="$(printf '\nx')" IFS="${IFS%x}"

मुझे पता है कि यह एक के बजाय दो क्रियाएं हैं, लेकिन मेरा इंडेंटेशन और पोर्टेबिलिटी OCD अब शांति पर है :) मैंने मूल रूप से इसे न्यूलाइन-केवल अलग-अलग आउटपुट को विभाजित करने में सक्षम होने के लिए विकसित किया था और मैं एक संशोधन का उपयोग करके समाप्त हुआ \rजो समाप्ति वर्ण के रूप में उपयोग करता है । डॉस आउटपुट समाप्त होने के लिए भी न्यूलाइन विभाजन कार्य करता है \r\n

IFS="$(printf '\n\r')"

0

मैं यहां किसी भी विकल्प से वास्तव में खुश नहीं था। इसी से मेरा काम बना है।

str=$(printf "%s" "first line")
str=$(printf "$str\n%s" "another line")
str=$(printf "$str\n%s" "and another line")

यह लिखने का एक बहुत ही थकाऊ तरीका है str=$(printf '%s\n' "first line" "another line" "and another line")(शेल आसानी से (या नहीं) कमांड प्रतिस्थापन से किसी भी अंतिम newlines को ट्रिम कर देगा)। यहाँ कई उत्तर पहले से ही printfविभिन्न रूपों में प्रचार करते हैं इसलिए मुझे यकीन नहीं है कि यह अलग जवाब के रूप में किसी भी मूल्य को जोड़ता है।
त्रिकाल

यह छोटे तारों के लिए है, लेकिन अगर आप चीजों को चुस्त-दुरुस्त रखना चाहते हैं और प्रत्येक पंक्ति वास्तव में 60 अक्षर लंबी है, तो यह इसे करने का एक अच्छा तरीका है। यह देखते हुए कि यह वह समाधान है जो मैं अंततः साथ गया था, यह कुछ जोड़ता है, अगर आपके लिए नहीं, तो भविष्य में खुद के लिए जब मैं निस्संदेह वापस लौटता हूं।
एडम के डीन

1
यहां तक ​​कि लंबे स्ट्रिंग्स के लिए मैं पसंद करता हूं printf '%s\n' "first line" \ (न्यूलाइन, इंडेंट) 'second line'आदि printf -v str। एक सबमिशन के बिना एक वेरिएबल को असाइन करने के लिए भी देखें ।
त्रिकाल
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.