बैश में एक स्ट्रिंग से एक नईलाइन कैसे निकालें


110

मेरे पास निम्न चर है।

echo "|$COMMAND|"

जो लौटता है

|
REBOOT|

मैं उस पहली नई लाइन को कैसे हटा सकता हूं?


7
यह एक ठग के रूप में क्यों चिह्नित है? यह सवाल एक गाड़ी वापसी को हटाने के बारे में है। कथित डुप्लिकेट प्रश्न जो इसे जोड़ता है वह व्हाट्सएप को हटाने के बारे में है, और केवल संयोग से गाड़ी के रिटर्न का उल्लेख करता है।
माइकल शेपर

1
@MichaelScheper सहमत हुए और फिर से खुल गए।
फेडोरक्वी 'एसओ स्टॉप हॉर्मिंग'

यहां की शब्दावली विषम है। यूनिक्स लाइन-टर्मिनेशन चरित्र \n(हेक्स 0x0A) को झूठ फ़ीड (एलएफ) कहा जाता है; यह कैरेक्टर कैरिज रिटर्न (CR) \r(हेक्स 0x0D) से अलग है जो विंडोज पर और कई नेटवर्क प्रोटोकॉल में दो-बाइट लाइन-एंड-एंडिंग क्रम CR LF में पहले बाइट के रूप में उपयोग किया जाता है।
ट्रिपलआई

जवाबों:


114

के अंतर्गत , कुछ बाशिन्दे हैं:

trकमांड द्वारा प्रतिस्थापित किया जा सकता // bashism :

COMMAND=$'\nREBOOT\r   \n'
echo "|${COMMAND}|"
|
   OOT
|

echo "|${COMMAND//[$'\t\r\n']}|"
|REBOOT   |

echo "|${COMMAND//[$'\t\r\n ']}|"
|REBOOT|

बैश के मैन पेज में पैरामीटर विस्तार और उद्धरण देखें :

man -Pless\ +/\/pattern bash
man -Pless\ +/\\\'string\\\' bash

man -Pless\ +/^\\\ *Parameter\\\ Exp bash
man -Pless\ +/^\\\ *QUOTING bash

आगे की...

@AlexJordan द्वारा पूछे जाने पर, यह सभी निर्दिष्ट वर्णों को दबा देगा । तो क्या होगा अगर $COMMANDइसमें स्पेस हो ...

COMMAND=$'         \n        RE BOOT      \r           \n'
echo "|$COMMAND|"
|
           BOOT      
|

CLEANED=${COMMAND//[$'\t\r\n']}
echo "|$CLEANED|"
|                 RE BOOT                 |

shopt -q extglob || { echo "Set shell option 'extglob' on.";shopt -s extglob;}

CLEANED=${CLEANED%%*( )}
echo "|$CLEANED|"
|                 RE BOOT|

CLEANED=${CLEANED##*( )}
echo "|$CLEANED|"
|RE BOOT|

कुछ ही समय:

COMMAND=$'         \n        RE BOOT      \r           \n'
CLEANED=${COMMAND//[$'\t\r\n']} && CLEANED=${CLEANED%%*( )}
echo "|${CLEANED##*( )}|"
|RE BOOT|

ध्यान दें: है extglobविकल्प सक्षम होने के लिए ( shopt -s extglobउपयोग करने के लिए) क्रम में *(...)वाक्य रचना।


1
यह BASH में एक चर से लाइनफीड को पट्टी करने का तरीका है। अन्य उत्तर अनावश्यक रूप से एक अतिरिक्त टीआर प्रक्रिया को लागू कर रहे हैं। BTW, यह रिक्त स्थान को हटाने का अतिरिक्त लाभ है!
पहुंचना

1
ध्यान दें कि यह एक स्ट्रिंग से आंतरिक स्थानों को भी हटा COMMAND="RE BOOT"; echo "|${COMMAND//[$'\t\r\n ']}|"देता है ... रिटर्न|REBOOT|
एलेक्स जॉर्डन

2
@AlexJordan हाँ, यह एक वांछित विशेषता है : आप \nइसे रोकने के बाद अंतरिक्ष को मिटा COMMAND="RE BOOT"; echo "|${COMMAND//[$'\t\r\n']}|"सकते हैं : वापस आ जाएगा |RE BOOT|
एफ। हौरी

2
पैटर्न कैसे काम कर रहा है ${COMMAND//[$'\t\r\n']}? मैंने सोचा था ${COMMAND//[\t\r\n]}कि बस काम करेगा, लेकिन यह नहीं किया। क्या $और एकल उद्धरण के लिए भी प्रतीक है?
हरदिवस

1
$ '' सिंटैक्स के बारे में, यह ANSI C उद्धृत है (जिसका उल्लेख wjordans answer में है)।
चीकू

81
echo "|$COMMAND|"|tr '\n' ' '

एक स्थान के साथ न्यूलाइन (POSIX / Unix में यह एक गाड़ी वापसी नहीं है) की जगह लेगा।

ईमानदार होने के लिए मैं बैश से दूर जाने के बारे में सोचूंगा, हालांकि कुछ अधिक समझदार। या पहली बार में इस विकृत डेटा को उत्पन्न करने से बचें।

हम्म, ऐसा लगता है कि यह एक भयानक सुरक्षा छेद भी हो सकता है, इस पर निर्भर करता है कि डेटा कहां से आ रहा है।


दिनांक एक कर्ल अनुरोध से आ रहा है जो उसी सर्वर पर है, मैं इसे नए संस्करण में कैसे डालूंगा? newvar = $ (गूंज "| $ COMMAND |" | tr '\ n' '')
मैट लीलैंड

2
हाँ। लेकिन कृपया मुझे बताएं कि आप लोगों को बिना पासवर्ड के अपने सर्वर को दूरस्थ रूप से रीबूट करने की अनुमति नहीं दे रहे हैं ...
रॉबिन ग्रीन

31
एक जगह की जगह छोड़ने केtr -d '\n' लिए आपने इस्तेमाल क्यों नहीं किया
एफ। होरी

3
बेकार पाइप कृपया! के tr '\n' ' ' <<< "|$COMMAND|"बजाय का उपयोग करेंecho ... | ...
एफ। होरी

12
@ F.Hauri: या बेकार है tr:"|${COMMAND//$'\n'}|"
rici

75

सभी गाड़ी के रिटर्न को हटाकर अपने वैरिएबल को साफ करें:

COMMAND=$(echo $COMMAND|tr -d '\n')

22
क्या वह स्ट्रिप लाइनफीड नहीं है? tr -d '\r'इसके बजाय नहीं होना चाहिए ?
इज़ी

3
एक अनियोजित वैरिएबल को गूँजने से सभी IFS वर्ण (नई पंक्ति, स्थान, डिफ़ॉल्ट रूप से टैब) को हटा दिया जाता है। इसलिए यदि आप ऐसा करने जा रहे हैं, तो आपको पता होना चाहिए कि सभी IFS अक्षर गिरा दिए गए हैं, और आपको इसकी आवश्यकता नहीं है tr। बस COMMAND=$(echo $COMMAND)एक समान प्रभाव देगा। जो, संभवतः, शैतान स्पॉन है क्योंकि यह एक नई प्रक्रिया को आमंत्रित करता है, लेकिन यह अभी भी मानव की आँखों के लिए बहुत छोटा और मीठा है और यदि आपके जीवन में एक या दो या दो से अधिक है तो आप हिट लेने के लिए तैयार हो सकते हैं :-)।
माइक एस

मैंने "लाइनफीड" कहने के लिए प्रश्न को अपडेट किया है, क्योंकि इसका उदाहरण दिखा रहा है कि यह एक लाइनफीड था, न कि गाड़ी वापसी। यह उत्तर अभी भी सही है, लेकिन शायद "कैरिज रिटर्न" के बजाय "लाइनफीड" कहने के लिए अपडेट किया जाना चाहिए?
बेंजामिन डब्ल्यू।

8

का उपयोग कर bash:

echo "|${COMMAND/$'\n'}|"

(ध्यान दें कि इस प्रश्न में नियंत्रण वर्ण एक 'न्यूलाइन' ( \n) है, न कि गाड़ी वापसी ( \r); बाद वाले का REBOOT|एकल लाइन पर आउटपुट होगा ।)

व्याख्या

बैश शैल पैरामीटर विस्तार का उपयोग करता है ${parameter/pattern/string}:

पैटर्न बस फ़ाइलनाम विस्तार में के रूप में एक पैटर्न का उत्पादन करने के लिए विस्तारित किया गया है। पैरामीटर का विस्तार किया गया है और इसके मूल्य के खिलाफ पैटर्न का सबसे लंबा मैच स्ट्रिंग के साथ बदल दिया गया है । [...] यदि स्ट्रिंग अशक्त है, तो पैटर्न के मिलान हटा दिए जाते हैं और / निम्नलिखित पैटर्न को छोड़ा जा सकता है।

$'' एएनएसआई-सी उद्धृत निर्माण का उपयोग भी करता है ताकि एक नई लाइन निर्दिष्ट की जा सके $'\n'। एक नई लाइन का उपयोग करना सीधे काम करेगा, हालांकि कम सुंदर:

echo "|${COMMAND/
}|"

पूर्ण उदाहरण

#!/bin/bash
COMMAND="$'\n'REBOOT"
echo "|${COMMAND/$'\n'}|"
# Outputs |REBOOT|

या, newlines का उपयोग कर:

#!/bin/bash
COMMAND="
REBOOT"
echo "|${COMMAND/
}|"
# Outputs |REBOOT|

6

मेरे लिए क्या काम था echo $testVar | tr "\n" " "

जहाँ testVar में मेरा वैरिएबल / स्क्रिप्ट-आउटपुट होता है


4

Tr का उपयोग करके और sed का उपयोग करके कई वर्णों को अलग करने के उदाहरण को दिखाने के लिए उत्तर जोड़ना। और हेक्सडंप का उपयोग करके चित्रण।

मेरे मामले में मैंने पाया था कि |awk '{print $2}'लाइन में अंतिम आइटम के awk प्रिंट के साथ समाप्त होने वाली एक कमांड में एक गाड़ी-वापसी \ r और साथ ही उद्धरण शामिल थे।

मैंने sed 's/["\n\r]//g'गाड़ी-वापसी और उद्धरण दोनों छीन लिए।

मैं भी इस्तेमाल कर सकता था tr -d '"\r\n'

sed -zयदि कोई व्यक्ति \ n पंक्ति-फ़ीड वर्ण को निकालना चाहे तो ध्यान देने योग्य है।

$ COMMAND=$'\n"REBOOT"\r   \n'

$ echo "$COMMAND" |hexdump -C
00000000  0a 22 52 45 42 4f 4f 54  22 0d 20 20 20 0a 0a     |."REBOOT".   ..|

$ echo "$COMMAND" |tr -d '"\r\n' |hexdump -C
00000000  52 45 42 4f 4f 54 20 20  20                       |REBOOT   |

$ echo "$COMMAND" |sed 's/["\n\r]//g' |hexdump -C
00000000  0a 52 45 42 4f 4f 54 20  20 20 0a 0a              |.REBOOT   ..|

$ echo "$COMMAND" |sed -z 's/["\n\r]//g' |hexdump -C
00000000  52 45 42 4f 4f 54 20 20  20                       |REBOOT   |

और यह प्रासंगिक है: गाड़ी वापसी, लाइनफीड और फॉर्म फीड क्या हैं?

  • CR == \ r == 0x0d
  • LF == \ n == 0x0a


2

यदि आप एक्सग्लोब विकल्प सक्षम के साथ बैश का उपयोग कर रहे हैं, तो आप केवल अनुगामी व्हाट्सएप को इसके माध्यम से हटा सकते हैं:

shopt -s extglob
COMMAND=$'\nRE BOOT\r   \n'
echo "|${COMMAND%%*([$'\t\r\n '])}|"

यह आउटपुट:

|
RE BOOT|

या # प्रमुख व्हाट्सएप को बदलने के लिए ## के साथ %% को बदलें।


1
यह कुछ अजीब आउटपुट के साथ एक आकर्षण की तरह काम करता है जो मुझे डॉक कमांड से मिला है। बहुत धन्यवाद!
develCuy
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.