बैश वैरिएबल से व्हाट्सप ट्रिम कैसे करें?


920

मेरे पास इस कोड के साथ एक शेल स्क्रिप्ट है:

var=`hg st -R "$path"`
if [ -n "$var" ]; then
    echo $var
fi

लेकिन सशर्त कोड हमेशा निष्पादित होता है, क्योंकि hg stहमेशा कम से कम एक न्यूलाइन वर्ण प्रिंट करता है ।

  • वहां से खाली स्थान के पट्टी के लिए एक सरल तरीका है $var(जैसे trim()में पीएचपी )?

या

  • क्या इस मुद्दे से निपटने का एक मानक तरीका है?

मैं sed या AWK का उपयोग कर सकता हूं , लेकिन मुझे लगता है कि इस समस्या का एक और अधिक सुंदर समाधान है।


3
संबंधित, यदि आप किसी पूर्णांक पर स्थान ट्रिम करना चाहते हैं और बस पूर्णांक प्राप्त करते हैं, तो $ (($ var)) के साथ लपेटें, और ऐसा तब भी कर सकते हैं जब डबल कोट्स के अंदर होता है। यह महत्वपूर्ण हो गया जब मैंने तिथि विवरण का उपयोग किया और फ़ाइलनाम के साथ।
वॉल्माइक

"क्या इस मुद्दे से निपटने का एक मानक तरीका है?" हां, [[के बजाय [] का उपयोग करें $ var=$(echo) $ [ -n $var ]; echo $? #undesired test return 0 $ [[ -n $var ]]; echo $? 1
user.friendly

यदि यह मदद करता है, तो कम से कम कहां यह Ubuntu 16.04 पर परीक्षण कर रहा है। निम्नलिखित मैचों का उपयोग हर तरह से ट्रिम करता है echo " This is a string of char " | xargs:। आप फिर भी पाठ में एक भी बोली है, तो आप निम्नलिखित कर सकते हैं: echo " This i's a string of char " | xargs -0। ध्यान दें कि मैंने xargs (4.6.0)
लुइस अल्वारादो

नई पंक्ति के कारण स्थिति सत्य नहीं है क्योंकि बैकटिक्स अंतिम नई पंक्ति को निगल जाता है। यह कुछ भी नहीं छापेगा test=`echo`; if [ -n "$test" ]; then echo "Not empty"; fi, हालांकि यह होगा test=`echo "a"`; if [ -n "$test" ]; then echo "Not empty"; fi- इसलिए अंत में सिर्फ एक नई रेखा से अधिक होना चाहिए।
मेकी

ए = "123 4 5 6"; बी = echo $A | sed -r 's/( )+//g';
ब्रजज़ीज़

जवाबों:


1021

आइए एक वैरिएबल को परिभाषित करें जिसमें अग्रणी, अनुगामी और मध्यवर्ती व्हाट्सएप हो:

FOO=' test test test '
echo -e "FOO='${FOO}'"
# > FOO=' test test test '
echo -e "length(FOO)==${#FOO}"
# > length(FOO)==16

कैसे सब खाली स्थान के हैं (जो चिह्नित दूर करने के लिए [:space:]में tr):

FOO=' test test test '
FOO_NO_WHITESPACE="$(echo -e "${FOO}" | tr -d '[:space:]')"
echo -e "FOO_NO_WHITESPACE='${FOO_NO_WHITESPACE}'"
# > FOO_NO_WHITESPACE='testtesttest'
echo -e "length(FOO_NO_WHITESPACE)==${#FOO_NO_WHITESPACE}"
# > length(FOO_NO_WHITESPACE)==12

केवल प्रमुख व्हाट्सएप कैसे निकालें:

FOO=' test test test '
FOO_NO_LEAD_SPACE="$(echo -e "${FOO}" | sed -e 's/^[[:space:]]*//')"
echo -e "FOO_NO_LEAD_SPACE='${FOO_NO_LEAD_SPACE}'"
# > FOO_NO_LEAD_SPACE='test test test '
echo -e "length(FOO_NO_LEAD_SPACE)==${#FOO_NO_LEAD_SPACE}"
# > length(FOO_NO_LEAD_SPACE)==15

केवल ट्रेलिंग व्हाट्सएप कैसे निकालें:

FOO=' test test test '
FOO_NO_TRAIL_SPACE="$(echo -e "${FOO}" | sed -e 's/[[:space:]]*$//')"
echo -e "FOO_NO_TRAIL_SPACE='${FOO_NO_TRAIL_SPACE}'"
# > FOO_NO_TRAIL_SPACE=' test test test'
echo -e "length(FOO_NO_TRAIL_SPACE)==${#FOO_NO_TRAIL_SPACE}"
# > length(FOO_NO_TRAIL_SPACE)==15

अग्रणी और अनुगामी दोनों रिक्त स्थान को कैसे निकालें - seds श्रृंखला :

FOO=' test test test '
FOO_NO_EXTERNAL_SPACE="$(echo -e "${FOO}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')"
echo -e "FOO_NO_EXTERNAL_SPACE='${FOO_NO_EXTERNAL_SPACE}'"
# > FOO_NO_EXTERNAL_SPACE='test test test'
echo -e "length(FOO_NO_EXTERNAL_SPACE)==${#FOO_NO_EXTERNAL_SPACE}"
# > length(FOO_NO_EXTERNAL_SPACE)==14

वैकल्पिक रूप से, अपने बैश इसका समर्थन करता है, तो आप बदल सकते हैं echo -e "${FOO}" | sed ...के साथ sed ... <<<${FOO}है, तो जैसे (सफेद स्थान को अनुगामी के लिए):

FOO_NO_TRAIL_SPACE="$(sed -e 's/[[:space:]]*$//' <<<${FOO})"

63
व्हाट्सएप के सभी रूपों को संभालने के लिए समाधान को सामान्य करने के लिए, अंतरिक्ष चरित्र को अंदर trऔर sedकमांड के साथ बदलें [[:space:]]। ध्यान दें कि sedदृष्टिकोण केवल सिंगल-लाइन इनपुट पर काम करेगा । उन दृष्टिकोणों के लिए जो मल्टी-लाइन इनपुट के साथ काम करते हैं और बैश की अंतर्निहित विशेषताओं का उपयोग करते हैं, @bashfu और @GuruM द्वारा जवाब देखें। @ निकोलस सुस्किन के समाधान का एक सामान्यीकृत, इनलाइन संस्करण इस तरह दिखेगा: trimmed=$([[ " test test test " =~ [[:space:]]*([^[:space:]]|[^[:space:]].*[^[:space:]])[[:space:]]* ]]; echo -n "${BASH_REMATCH[1]}")
mklement0

7
यदि आप अक्सर ऐसा करते हैं, तो आपके लिए अपील alias trim="sed -e 's/^[[:space:]]*//g' -e 's/[[:space:]]*\$//g'"करना ~/.profileआपको उपयोग करने की अनुमति देता है echo $SOMEVAR | trimऔर cat somefile | trim
उदाहरण

मैंने एक sedसमाधान लिखा है जो केवल दो के बजाय एक एकल अभिव्यक्ति का उपयोग करता है sed -r 's/^\s*(\S+(\s+\S+)*)\s*$/\1/':। यह व्हाट्सएप को अग्रणी और अनुगामी बनाता है, और बीच में गैर-व्हाट्सएप वर्णों के किसी भी व्हाट्सएप-पृथक अनुक्रम को पकड़ता है। का आनंद लें!
विक्टर ज़मानियन

@VictorZamanian यदि इनपुट में केवल व्हाट्सएप है तो आपका समाधान काम नहीं करता है। MattyV द्वारा दिए गए दो-पैटर्न सेड सॉल्यूशंस और मेरे द्वारा व्हाट्सएप केवल इनपुट के साथ ठीक काम करते हैं।
Torben

@ टॉर्बन फेयर पॉइंट। मुझे लगता है कि एकल अभिव्यक्ति को सशर्त बनाया जा सकता है, साथ ही |, इसे कई के बजाय एक एकल अभिव्यक्ति के रूप में रखने के लिए।
विक्टर ज़ामेनियन

964

एक सरल उत्तर है:

echo "   lol  " | xargs

Xargs आपके लिए ट्रिमिंग करेगा। यह एक कमांड / प्रोग्राम है, कोई पैरामीटर नहीं है, छंटनी की गई स्ट्रिंग को लौटाता है, जैसा कि आसान है!

नोट: यह सभी आंतरिक रिक्त स्थान नहीं निकालता है इसलिए "foo bar"समान रहता है; यह नहीं बन जाता है "foobar"। हालांकि, कई स्थानों को एकल स्थानों के लिए संघनित किया "foo bar"जाएगा , इसलिए यह बन जाएगा "foo bar"। इसके अलावा यह लाइनों के पात्रों को समाप्त नहीं करता है।


27
अच्छा लगा। यह वास्तव में अच्छी तरह से काम करता है। मैंने इसे पाइप करने का निर्णय लिया है xargs echoकि मैं क्या कर रहा हूं, इसके बारे में क्रिया करना है, लेकिन अपने आप में xargs डिफ़ॉल्ट रूप से गूंज का उपयोग करेगा।
विल

24
अच्छी चाल, लेकिन केयरफुल बनो, आप इसे एक-लाइन स्ट्रिंग के लिए उपयोग कर सकते हैं, लेकिन butby xargs design− यह सिर्फ मल्टी-लाइन पाइप की गई सामग्री के साथ ट्रिमिंग नहीं करेगा। sed तब आपका दोस्त है
जोकेले डेललांडे

22
Xargs के साथ एकमात्र समस्या यह है कि यह एक नई रूपरेखा पेश करेगा, यदि आप newline को बंद रखना चाहते हैं तो मैं sed 's/ *$//'विकल्प के रूप में सिफारिश करूंगा । आप देख सकते हैं xargsइस तरह न्यू लाइन: echo -n "hey thiss " | xargs | hexdump आप देखेंगे न्यू लाइन है। यदि आप ऐसा ही करते हैं : आप देखेंगे , कोई नई रेखा नहीं। 0a73asedecho -n "hey thiss " | sed 's/ *$//' | hexdump0073

8
सावधान; यह बहुत मुश्किल से टूटेगा यदि स्ट्रिंग टू xargs में अधिशेष रिक्त स्थान होते हैं। जैसे "यह एक तर्क है"। xargs चार में विभाजित होगा।
बोस

64
ये गलत है। 1. यह में बदल a<space><space>bजाएगा a<space>b। 2. इससे भी अधिक: यह बदल a"b"c'd'eजाएगा abcde। 3. इससे भी अधिक: यह विफल होगा a"b, आदि
साशा

357

एक समाधान है जो केवल बैश बिल्ट-इन वाइल्डकार्ड का उपयोग करता है :

var="    abc    "
# remove leading whitespace characters
var="${var#"${var%%[![:space:]]*}"}"
# remove trailing whitespace characters
var="${var%"${var##*[![:space:]]}"}"   
printf '%s' "===$var==="

यहाँ एक समारोह में लिपटे एक ही है:

trim() {
    local var="$*"
    # remove leading whitespace characters
    var="${var#"${var%%[![:space:]]*}"}"
    # remove trailing whitespace characters
    var="${var%"${var##*[![:space:]]}"}"   
    printf '%s' "$var"
}

आप उद्धृत रूप में छंटनी की जाने वाली स्ट्रिंग को पास करते हैं। उदाहरण के लिए:

trim "   abc   "

इस समाधान के बारे में एक अच्छी बात यह है कि यह किसी भी POSIX- अनुरूप शेल के साथ काम करेगा।

संदर्भ


17
चतुर! यह मेरा पसंदीदा समाधान है क्योंकि यह बिल्ट-इन बैश कार्यक्षमता का उपयोग करता है। पोस्ट करने का शुक्रिया! @San, यह दो नेस्टेड स्ट्रिंग ट्रिम्स है। उदाहरण के लिए, s=" 1 2 3 "; echo \""${s%1 2 3 }"\"अंत से सब कुछ ट्रिम हैं, अग्रणी लौटने " "। इसके 1 2 3 साथ सबबिंग [![:space:]]*"पहले गैर-अंतरिक्ष चरित्र को खोजने के लिए, उसके बाद इसे और उसके बाद सब कुछ" को बताती है। का उपयोग %%करने के बजाय %ट्रिम-से-एंड आपरेशन लालची बनाता है। यह एक गैर-लालची ट्रिम-से-स्टार्ट में नेस्टेड है, इसलिए वास्तव में, आप " "शुरू से ट्रिम करते हैं। फिर, अंतिम रिक्त स्थान के लिए%, #, और * स्वैप करें। बैम!
मार्क जी।

2
मुझे कोई अवांछित दुष्प्रभाव नहीं मिला है, और मुख्य कोड अन्य POSIX जैसे गोले के साथ भी काम करता है। हालाँकि, Solaris 10 के तहत, यह /bin/shकेवल साथ काम नहीं करता है ( /usr/xpg4/bin/shलेकिन यह सामान्य स्क्रिप्स के साथ उपयोग नहीं किया जाएगा)।
vinc17

9
सेड, ट्राई आदि का उपयोग करने की तुलना में बहुत बेहतर समाधान, क्योंकि यह बहुत तेज़ है, किसी भी कांटे () से बचना। गति में साइग्विन अंतर पर परिमाण के आदेश हैं।
जीन पावलोवस्की

9
@ पहले तो मैं स्तब्ध था क्योंकि मुझे लगा कि ये नियमित अभिव्यक्ति हैं। वो नहीं हैं। बल्कि, यह पदार्थ मिलान ( tldp.org/LDP/abs ) में उपयोग किया जाने वाला पैटर्न मिलान वाक्यविन्यास ( gnu.org/software/bash/manual/html_node/Pattern-Matching.html , wiki.bash-hackers.org/syntax/pattern ) है। /html/string-manipulation.html )। तो ${var%%[![:space:]]*}कहते हैं " varअपने सबसे लंबे प्रतिस्थापन से हटा दें जो एक गैर-अंतरिक्ष चरित्र से शुरू होता है"। इसका मतलब है कि आपको केवल अग्रणी स्थान (एस) के साथ छोड़ दिया जाता है, जिसे आप बाद में हटा देते हैं ${var#..। निम्नलिखित पंक्ति (अनुगामी) विपरीत है।
ओहद श्नाइडर

8
यह आदर्श समाधान है। एक या अधिक बाहरी प्रक्रियाओं forking (जैसे, awk, sed, tr, xargs) एक एकल स्ट्रिंग से ट्रिम खाली स्थान के लिए केवल मौलिक पागल है - विशेष रूप से जब सबसे गोले (बैश सहित) पहले से ही देशी स्ट्रिंग सुविधाओं munging आउट-ऑफ-द-बॉक्स प्रदान करते हैं।
सेसिल करी

80

बैश में पैरामीटर विस्तार नामक एक विशेषता है , जो अन्य बातों के अलावा, तथाकथित पैटर्न के आधार पर स्ट्रिंग प्रतिस्थापन की अनुमति देता है (पैटर्न नियमित अभिव्यक्ति के समान होते हैं, लेकिन मौलिक अंतर और सीमाएं हैं)। [फ्लॉसेंस की मूल पंक्ति: बैश में नियमित भाव हैं, लेकिन वे अच्छी तरह से छिपे हुए हैं:]

निम्नलिखित दर्शाता है कि एक चर मान से सभी सफेद स्थान (यहां तक ​​कि इंटीरियर से भी) को कैसे हटाया जाए ।

$ var='abc def'
$ echo "$var"
abc def
# Note: flussence's original expression was "${var/ /}", which only replaced the *first* space char., wherever it appeared.
$ echo -n "${var//[[:space:]]/}"
abcdef

2
या बल्कि, यह एक var के बीच में रिक्त स्थान के लिए काम करता है, लेकिन तब नहीं जब मैं इसे अंत में एंकर करने का प्रयास करता हूं।
पॉल टॉम्बलिन

क्या इससे कोई मदद मिलती है? मैनपेज से: "$ {पैरामीटर / पैटर्न / स्ट्रिंग} [...] यदि पैटर्न% से शुरू होता है, तो इसे पैरामीटर के विस्तारित मूल्य के अंत में मेल खाना चाहिए।"

@ नहीं, तो वे वास्तव में नियमित अभिव्यक्ति नहीं हैं, लेकिन कुछ इसी तरह?
पॉल टॉम्बलिन

3
वे रेगेक्स हैं, बस एक अजीब बोली।

13
${var/ /}पहला अंतरिक्ष वर्ण निकालता है। ${var// /}सभी अंतरिक्ष पात्रों को निकालता है। केवल इस निर्माण के साथ व्हाट्सएप को अग्रणी और अनुगामी बनाने के लिए ट्रिम करने का कोई तरीका नहीं है।
गिल्स एसओ- बुराई को रोकें '

60

एक स्ट्रिंग के अंत और शुरुआत (पंक्ति वर्णों के अंत सहित) से सभी रिक्त स्थान निकालने के लिए:

echo $variable | xargs echo -n

इससे डुप्लिकेट स्थान भी निकल जाएंगे:

echo "  this string has a lot       of spaces " | xargs echo -n

प्रोडक्शंस: 'इस स्ट्रिंग में बहुत सी जगहें हैं'


5
मूल रूप से xargs स्ट्रिंग से सभी सीमांकक को निकालता है। डिफ़ॉल्ट रूप से यह अंतरिक्ष को सीमांकक के रूप में उपयोग करता है (इसे -d विकल्प द्वारा बदला जा सकता है)।
15

4
यह अब तक का सबसे साफ (छोटा और पठनीय दोनों) समाधान है।
पर्ट्का

आपको आखिर क्यों चाहिए echo -n? echo " my string " | xargsएक ही आउटपुट है।
bfontaine

इको-एन लाइन के अंत को भी दूर करता है
racachach

55

एक अग्रणी और एक अनुगामी अंतरिक्ष पट्टी

trim()
{
    local trimmed="$1"

    # Strip leading space.
    trimmed="${trimmed## }"
    # Strip trailing space.
    trimmed="${trimmed%% }"

    echo "$trimmed"
}

उदाहरण के लिए:

test1="$(trim " one leading")"
test2="$(trim "one trailing ")"
test3="$(trim " one leading and one trailing ")"
echo "'$test1', '$test2', '$test3'"

आउटपुट:

'one leading', 'one trailing', 'one leading and one trailing'

सभी प्रमुख और अनुगामी स्थानों को पट्टी करें

trim()
{
    local trimmed="$1"

    # Strip leading spaces.
    while [[ $trimmed == ' '* ]]; do
       trimmed="${trimmed## }"
    done
    # Strip trailing spaces.
    while [[ $trimmed == *' ' ]]; do
        trimmed="${trimmed%% }"
    done

    echo "$trimmed"
}

उदाहरण के लिए:

test4="$(trim "  two leading")"
test5="$(trim "two trailing  ")"
test6="$(trim "  two leading and two trailing  ")"
echo "'$test4', '$test5', '$test6'"

आउटपुट:

'two leading', 'two trailing', 'two leading and two trailing'

9
यह केवल 1 स्पेस कैरेक्टर को ट्रिम करेगा। इसलिए प्रतिध्वनि का परिणाम होता है'hello world ', 'foo bar', 'both sides '
जो

@ जो मैंने एक बेहतर विकल्प जोड़ा।
वेजेंड्रिया

42

ग्लोबिंग पर बैश गाइड अनुभाग से

एक पैरामीटर विस्तार में एक extglob का उपयोग करने के लिए

 #Turn on extended globbing  
shopt -s extglob  
 #Trim leading and trailing whitespace from a variable  
x=${x##+([[:space:]])}; x=${x%%+([[:space:]])}  
 #Turn off extended globbing  
shopt -u extglob  

यहां फ़ंक्शन में लिपटे एक ही कार्यक्षमता है (नोट: फ़ंक्शन के लिए पारित इनपुट स्ट्रिंग को उद्धृत करने की आवश्यकता है):

trim() {
    # Determine if 'extglob' is currently on.
    local extglobWasOff=1
    shopt extglob >/dev/null && extglobWasOff=0 
    (( extglobWasOff )) && shopt -s extglob # Turn 'extglob' on, if currently turned off.
    # Trim leading and trailing whitespace
    local var=$1
    var=${var##+([[:space:]])}
    var=${var%%+([[:space:]])}
    (( extglobWasOff )) && shopt -u extglob # If 'extglob' was off before, turn it back off.
    echo -n "$var"  # Output trimmed string.
}

उपयोग:

string="   abc def ghi  ";
#need to quote input-string to preserve internal white-space if any
trimmed=$(trim "$string");  
echo "$trimmed";

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

trim() {
    shopt -s extglob
    set -- "${1##+([[:space:]])}"
    printf "%s" "${1%%+([[:space:]])}" 
}

इसलिए:

$ s=$'\t\n \r\tfoo  '
$ shopt -u extglob
$ shopt extglob
extglob         off
$ printf ">%q<\n" "$s" "$(trim "$s")"
>$'\t\n \r\tfoo  '<
>foo<
$ shopt extglob
extglob         off

2
जैसा कि आपने ट्रिम मनाया है () केवल व्हाट्सएप के प्रमुख और अनुगामी को निकालता है।
गुरु

जैसा कि पहले ही उल्लेख किया जा चुका है कि आपको फंक्शन पैरामीटर को एक उद्धृत स्ट्रिंग यानी $ (ट्रिम "$ स्ट्रिंग") के बजाय $ (ट्रिम $ स्ट्रिंग) के रूप में पारित करने की आवश्यकता है। मैंने सही उपयोग दिखाने के लिए कोड अपडेट किया है। धन्यवाद।
गुरु

जितना मैं खोल विकल्पों के बारे में जानने की सराहना करता हूं, मुझे नहीं लगता कि अंतिम परिणाम केवल 2 पैटर्न प्रतिस्थापन करने की तुलना में अधिक सुरुचिपूर्ण है
sehe

ध्यान दें कि (बैश के एक हालिया पर्याप्त संस्करण के साथ?), आप विकल्प को पुनर्स्थापित करने के लिए तंत्र को सरल बना सकते हैं extglob, का उपयोग करके shopt -p: बस local restore="$(shopt -p extglob)" ; shopt -s extglobअपने फ़ंक्शन की शुरुआत में लिखें , और eval "$restore"अंत में (सिवाय, दी गई, बुराई बुराई है ...)।
मैलन

महान समाधान! एक संभावित सुधार: ऐसा लगता है कि [[:space:]]इसके साथ प्रतिस्थापित किया जा सकता है, ठीक है, एक स्थान: ${var##+( )}और ${var%%+( )}साथ ही काम करते हैं और वे पढ़ने में आसान होते हैं।
DKroot

40

आप बस के साथ ट्रिम कर सकते हैं echo:

foo=" qsdqsd qsdqs q qs   "

# Not trimmed
echo \'$foo\'

# Trim
foo=`echo $foo`

# Trimmed
echo \'$foo\'

यह एक में कई सन्निहित रिक्त स्थान को ध्वस्त करता है।
इवगेनी सर्गेव

7
जब आपने fooवाइल्डकार्ड शामिल किया तो क्या आपने इसे आज़माया? जैसे, foo=" I * have a wild card"... आश्चर्य! इसके अलावा यह एक में कई सन्निहित रिक्त स्थान ढह जाता है।
ग्नौरफ_ग्निउरफ

5
यह एक उत्कृष्ट समाधान है यदि आप: 1. छोरों पर कोई स्थान नहीं चाहते हैं। प्रत्येक शब्द के बीच केवल एक स्थान चाहते हैं 3. बिना किसी वाइल्डकार्ड के एक नियंत्रित इनपुट के साथ काम कर रहे हैं। यह अनिवार्य रूप से एक बुरी तरह से स्वरूपित सूची को अच्छे में बदल देता है।
डी

वाइल्डकार्ड @gniourf_gniourf +1 का अच्छा अनुस्मारक। फिर भी एक उत्कृष्ट समाधान, वैम्प। आप को भी +1।
डॉ। बीको

25

मैंने हमेशा इसे सेड के साथ किया है

  var=`hg st -R "$path" | sed -e 's/  *$//'`

यदि कोई अधिक सुरुचिपूर्ण समाधान है, मुझे आशा है कि कोई इसे पोस्ट करेगा।


आप के लिए वाक्यविन्यास समझा सकते हैं sed?
farid99

2
नियमित अभिव्यक्ति सभी अनुगामी व्हाट्सएप से मेल खाती है और इसे कुछ भी नहीं के साथ बदल देती है।
पॉल टॉम्बलिन

4
प्रमुख व्हाट्सएप के बारे में कैसे?
कियान चेन

यह सभी अनुगामी व्हाट्सएप को स्ट्रिप्स करता है sed -e 's/\s*$//'। स्पष्टीकरण: 's' का अर्थ है खोज, '\' s का अर्थ है सभी व्हाट्सएप, '*' का अर्थ है शून्य या कई, '$' का अर्थ है पंक्ति के अंत तक और '//' का अर्थ है एक खाली स्ट्रिंग के साथ सभी मैचों का विकल्प। ।
क्रेग

'S / * $ //' में, एकल स्थान के बजाय तारांकन से पहले 2 स्थान क्यों हैं? क्या वह टाइपो है?
ब्रेंट212


24

बैश के विस्तारित पैटर्न मिलान सुविधाओं को सक्षम करने ( shopt -s extglob) के साथ, आप इसका उपयोग कर सकते हैं:

{trimmed##*( )}

प्रमुख स्थानों की एक मनमानी राशि निकालने के लिए।


बहुत खूब! मुझे लगता है कि यह सबसे हल्का और सुरुचिपूर्ण समाधान है।
डबियसजिम

1
एक समान, लेकिन अधिक सामान्य समाधान के लिए नीचे @ गुरु का पद देखें (क) सफेद स्थान के सभी रूपों से संबंधित है और (बी) सफेद स्थान को पीछे छोड़ता है।
mklement0

एक फ़ंक्शन के रूप में मेरे कोड स्निपेट को फिर से लिखने के लिए परेशानी लेने के लिए @mkelement +1। धन्यवाद
गुरु

OpenBSD के डिफ़ॉल्ट / बिन / ksh के साथ भी काम करता है। /bin/sh -o posixकाम करता है, लेकिन मुझे संदेह है।
क्लिंट पच

यहां बैश विज़ार्ड नहीं; क्या है trimmed? क्या यह बिल्ट-इन चीज है या चर जिसे ट्रिम किया जा रहा है?
अभिजीत सरकार

19
# Trim whitespace from both ends of specified parameter

trim () {
    read -rd '' $1 <<<"${!1}"
}

# Unit test for trim()

test_trim () {
    local foo="$1"
    trim foo
    test "$foo" = "$2"
}

test_trim hey hey &&
test_trim '  hey' hey &&
test_trim 'ho  ' ho &&
test_trim 'hey ho' 'hey ho' &&
test_trim '  hey  ho  ' 'hey  ho' &&
test_trim $'\n\n\t hey\n\t ho \t\n' $'hey\n\t ho' &&
test_trim $'\n' '' &&
test_trim '\n' '\n' &&
echo passed

2
गजब का! सरल और प्रभावी! स्पष्ट रूप से मेरा पसंदीदा समाधान। धन्यवाद!
xebeche

1
@CraigMcQueen यह वैरिएबल वैल्यू है, जैसा readकि इसके नाम $ 1 के वैरिएबल में इसके वैल्यू $ {! 1}
कुंभ पावर

2
ट्रिम () फ़ंक्शन का पैरामीटर एक चर नाम है: कॉल को ट्रिम () test_trim () के अंदर देखें। ट्रिम के भीतर () जैसा कि test_trim () से कहा जाता है, $ 1 का विस्तार foo और $ {! 1} से $ foo तक फैलता है (अर्थात, परिवर्तनीय फू की वर्तमान सामग्री के लिए)। 'चर अप्रत्यक्ष' के लिए बैश मैनुअल खोजें।
flabdablet 12

1
इस छोटे से संशोधन के बारे में, एक कॉल में कई संस्करणों को ट्रिम करने के लिए कैसे? trim() { while [[ $# -gt 0 ]]; do read -rd '' $1 <<<"${!1}"; shift; done; }
जीन पावलोवस्की

2
@AquariusPower को वन-लाइनर संस्करण के लिए एक सब-रील में इको का उपयोग करने की कोई आवश्यकता नहीं है, बस read -rd '' str <<<"$str"करेंगे।
flabdablet

12

बहुत सारे उत्तर हैं, लेकिन मेरा मानना ​​है कि मेरी अभी-अभी लिखी गई स्क्रिप्ट का उल्लेख करने लायक है क्योंकि:

  • यह सफलतापूर्वक बैश / डैश / बिजीबॉक्स शेल में परीक्षण किया गया था
  • यह बहुत छोटा है
  • यह बाहरी आदेशों पर निर्भर नहीं करता है और इसके लिए कांटा (-> तेज़ और कम संसाधन उपयोग) की आवश्यकता नहीं है
  • यह उम्मीद के मुताबिक काम करता है:
    • यह सब छीन लेता है शुरुआत और अंत से रिक्त स्थान और टैब , लेकिन अधिक नहीं
    • महत्वपूर्ण: यह स्ट्रिंग के बीच में से कुछ भी नहीं निकालता है (कई अन्य उत्तर करते हैं), यहां तक ​​कि नए समाचार भी बने रहेंगे
    • विशेष: "$*"एक स्थान का उपयोग करके कई तर्कों को जोड़ता है। यदि आप केवल पहला तर्क ट्रिम और आउटपुट करना चाहते हैं, उपयोग करें"$1" इसके बजाय
    • अगर फ़ाइल नाम पैटर्न आदि के मिलान में कोई समस्या नहीं है

लिपी:

trim() {
  local s2 s="$*"
  until s2="${s#[[:space:]]}"; [ "$s2" = "$s" ]; do s="$s2"; done
  until s2="${s%[[:space:]]}"; [ "$s2" = "$s" ]; do s="$s2"; done
  echo "$s"
}

उपयोग:

mystring="   here     is
    something    "
mystring=$(trim "$mystring")
echo ">$mystring<"

आउटपुट:

>here     is
    something<

सी में बाह यह लागू करने के लिए सरल हो जाएगा!
निल्स

ज़रूर। दुर्भाग्य से, यह सी नहीं है और कभी-कभी आप बाहरी उपकरणों को कॉल करने से बचना चाहते हैं
डैनियल एल्डर

कोड को अधिक पठनीय और कॉपी-पास्ट दोनों संगत बनाने के लिए, आप कोष्ठक को भागे हुए वर्णों में बदल सकते हैं:[\ \t]
leondepeon

@leondepeon क्या आपने यह कोशिश की? मैंने कोशिश की जब मैंने इसे लिखा और फिर से कोशिश की, और आपका सुझाव किसी भी मार, डैश, बिजीबॉक्स में काम नहीं करता
डैनियल एल्डर

@DanielAlder मैंने किया था, लेकिन जैसा कि 3 साल पहले ही है, मुझे वह कोड नहीं मिल रहा है जहां मैंने इसका उपयोग किया था। अब हालांकि, मैं शायद [[:space:]]अन्य उत्तरों में से एक में उपयोग
करूंगा

11

आप पुराने स्कूल का उपयोग कर सकते हैं tr। उदाहरण के लिए, यह एक गिट रिपॉजिटरी, व्हाट्सएप में छपी संशोधित फाइलों की संख्या को लौटाता है।

MYVAR=`git ls-files -m|wc -l|tr -d ' '`

1
यह व्हाट्सएप को आगे और पीछे से ट्रिम नहीं करता है - यह स्ट्रिंग से सभी व्हाट्सएप को हटा देता है।
निक

11

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

text="   trim my edges    "

trimmed=$text
trimmed=${trimmed##+( )} #Remove longest matching series of spaces from the front
trimmed=${trimmed%%+( )} #Remove longest matching series of spaces from the back

echo "<$trimmed>" #Adding angle braces just to make it easier to confirm that all spaces are removed

#Result
<trim my edges>

एक ही परिणाम के लिए कम लाइनों पर डाल करने के लिए:

text="    trim my edges    "
trimmed=${${text##+( )}%%+( )}

1
मेरे लिए काम नहीं किया। पहले वाले ने एक अनमैरिड स्ट्रिंग छपवाई। दूसरे ने खराब प्रतिस्थापन को फेंक दिया। क्या आप बता सकते हैं कि यहाँ क्या हो रहा है?
संगीत 3

1
@ musicin3d: यह एक ऐसी साइट है जिसका उपयोग मैं अक्सर करता हूं कि अधिक विवरण के लिए बैश खोज में चर हेरफेर कैसे काम करता है${var##Pattern} । इसके अलावा, यह साइट बैश पैटर्न की व्याख्या करती है । तो ##मतलब सामने से दिए गए पैटर्न को %%हटा दें और इसका मतलब है कि दिए गए पैटर्न को पीछे से हटा दें। +( )भाग पैटर्न है और यह "एक या एक अंतरिक्ष के अधिक घटना" का अर्थ है
gMale

मज़ेदार, इसने प्रॉम्प्ट में काम किया, लेकिन बैश स्क्रिप्ट फ़ाइल में ट्रांसपोज़ करने के बाद नहीं।
डॉ। बीको

अजीब। क्या यह दोनों उदाहरणों में समान बैश संस्करण है?
गमले

11
# Strip leading and trailing white space (new line inclusive).
trim(){
    [[ "$1" =~ [^[:space:]](.*[^[:space:]])? ]]
    printf "%s" "$BASH_REMATCH"
}

या

# Strip leading white space (new line inclusive).
ltrim(){
    [[ "$1" =~ [^[:space:]].* ]]
    printf "%s" "$BASH_REMATCH"
}

# Strip trailing white space (new line inclusive).
rtrim(){
    [[ "$1" =~ .*[^[:space:]] ]]
    printf "%s" "$BASH_REMATCH"
}

# Strip leading and trailing white space (new line inclusive).
trim(){
    printf "%s" "$(rtrim "$(ltrim "$1")")"
}

या

# Strip leading and trailing specified characters.  ex: str=$(trim "$str" $'\n a')
trim(){
    if [ "$2" ]; then
        trim_chrs="$2"
    else
        trim_chrs="[:space:]"
    fi

    [[ "$1" =~ ^["$trim_chrs"]*(.*[^"$trim_chrs"])["$trim_chrs"]*$ ]]
    printf "%s" "${BASH_REMATCH[1]}"
}

या

# Strip leading specified characters.  ex: str=$(ltrim "$str" $'\n a')
ltrim(){
    if [ "$2" ]; then
        trim_chrs="$2"
    else
        trim_chrs="[:space:]"
    fi

    [[ "$1" =~ ^["$trim_chrs"]*(.*[^"$trim_chrs"]) ]]
    printf "%s" "${BASH_REMATCH[1]}"
}

# Strip trailing specified characters.  ex: str=$(rtrim "$str" $'\n a')
rtrim(){
    if [ "$2" ]; then
        trim_chrs="$2"
    else
        trim_chrs="[:space:]"
    fi

    [[ "$1" =~ ^(.*[^"$trim_chrs"])["$trim_chrs"]*$ ]]
    printf "%s" "${BASH_REMATCH[1]}"
}

# Strip leading and trailing specified characters.  ex: str=$(trim "$str" $'\n a')
trim(){
    printf "%s" "$(rtrim "$(ltrim "$1" "$2")" "$2")"
}

या

मस्जिद के विस्तार पर निर्माण ...

# Strip leading and trailing white space (new line inclusive).
trim(){
    printf "%s" "`expr "$1" : "^[[:space:]]*\(.*[^[:space:]]\)[[:space:]]*$"`"
}

या

# Strip leading white space (new line inclusive).
ltrim(){
    printf "%s" "`expr "$1" : "^[[:space:]]*\(.*[^[:space:]]\)"`"
}

# Strip trailing white space (new line inclusive).
rtrim(){
    printf "%s" "`expr "$1" : "^\(.*[^[:space:]]\)[[:space:]]*$"`"
}

# Strip leading and trailing white space (new line inclusive).
trim(){
    printf "%s" "$(rtrim "$(ltrim "$1")")"
}

8

मैंने स्क्रिप्ट देखी है कि काम करने के लिए केवल चर असाइनमेंट का उपयोग करें:

$ xyz=`echo -e 'foo \n bar'`
$ echo $xyz
foo bar

व्हॉट्सएप स्वचालित रूप से संकुचित और छंटनी की जाती है। एक को शेल मेटाचैकर (संभावित इंजेक्शन जोखिम) से सावधान रहना होगा।

मैं हमेशा शेल कंडीशन में दोहरे-परिवर्तनशील चर प्रतिस्थापन की सिफारिश करूंगा:

if [ -n "$var" ]; then

चूंकि चर में कोई -o या अन्य सामग्री जैसी कोई चीज आपके परीक्षण तर्कों में संशोधन कर सकती है।


3
यह इसके $xyzसाथ प्रयोग echoनहीं किया गया है जो कि व्हॉट्सएप को समतल करता है, कि चर असाइनमेंट को। अपने उदाहरण में चर में छंटनी की गई मूल्य को संग्रहीत करने के लिए, आपको उपयोग करना होगा xyz=$(echo -n $xyz)। साथ ही, यह दृष्टिकोण संभावित रूप से अवांछित पथनाम विस्तार (ग्लोबिंग) के अधीन है।
mklement0

यह गलत है, xyzचर में मान छंटनी नहीं है।
caesarsol

7
var='   a b c   '
trimmed=$(echo $var)

1
अगर किसी दो शब्दों के बीच एक से अधिक स्थान हैं तो यह काम नहीं करेगा। कोशिश करें: echo $(echo "1 2 3")(1, 2 और 3 के बीच दो रिक्त स्थान के साथ)।
२२:२३ पर २२

7

मैं बस sed का उपयोग करेगा:

function trim
{
    echo "$1" | sed -n '1h;1!H;${;g;s/^[ \t]*//g;s/[ \t]*$//g;p;}'
}

क) सिंगल-लाइन स्ट्रिंग पर उपयोग का उदाहरण

string='    wordA wordB  wordC   wordD    '
trimmed=$( trim "$string" )

echo "GIVEN STRING: |$string|"
echo "TRIMMED STRING: |$trimmed|"

आउटपुट:

GIVEN STRING: |    wordA wordB  wordC   wordD    |
TRIMMED STRING: |wordA wordB  wordC   wordD|

बी) मल्टी-लाइन स्ट्रिंग पर उपयोग का उदाहरण

string='    wordA
   >wordB<
wordC    '
trimmed=$( trim "$string" )

echo -e "GIVEN STRING: |$string|\n"
echo "TRIMMED STRING: |$trimmed|"

आउटपुट:

GIVEN STRING: |    wordAA
   >wordB<
wordC    |

TRIMMED STRING: |wordAA
   >wordB<
wordC|

ग) अंतिम नोट:
यदि आप सिंगल-लाइन स्ट्रिंग के लिए फ़ंक्शन का उपयोग करना पसंद नहीं करते हैं तो आप बस "याद रखने में आसान" कमांड का उपयोग कर सकते हैं:

echo "$string" | sed -e 's/^[ \t]*//' | sed -e 's/[ \t]*$//'

उदाहरण:

echo "   wordA wordB wordC   " | sed -e 's/^[ \t]*//' | sed -e 's/[ \t]*$//'

आउटपुट:

wordA wordB wordC

मल्टी-लाइन स्ट्रिंग्स पर उपरोक्त का उपयोग करना काम करेगा , लेकिन कृपया ध्यान दें कि यह किसी भी अनुगामी / अग्रणी आंतरिक मल्टीपल स्पेस को भी काट देगा, जैसा कि गुरु ने टिप्पणियों में देखा है।

string='    wordAA
    >four spaces before<
 >one space before<    '
echo "$string" | sed -e 's/^[ \t]*//' | sed -e 's/[ \t]*$//'

आउटपुट:

wordAA
>four spaces before<
>one space before<

इसलिए यदि आप उन स्थानों को रखने के लिए मन रखते हैं, तो कृपया मेरे उत्तर की शुरुआत में फ़ंक्शन का उपयोग करें!

डी) फ़ंक्शन ट्रिम के अंदर उपयोग किए जाने वाले मल्टी-लाइन स्ट्रिंग्स पर "सिंटैक्स" को ढूंढें और प्रतिस्थापित करें।

sed -n '
# If the first line, copy the pattern to the hold buffer
1h
# If not the first line, then append the pattern to the hold buffer
1!H
# If the last line then ...
$ {
    # Copy from the hold to the pattern buffer
    g
    # Do the search and replace
    s/^[ \t]*//g
    s/[ \t]*$//g
    # print
    p
}'

नोट: जैसा कि @mkelement ने सुझाव दिया है कि यह मल्टी-लाइन स्ट्रिंग के लिए काम नहीं करेगा, हालांकि इसे सिंगल-लाइन स्ट्रिंग्स के लिए काम करना चाहिए।
गुरु

1
आप गलत हैं: यह मल्टी-लाइन स्ट्रिंग्स पर भी काम करता है। बस इसे बाहर का परीक्षण! :)
Luca Borrione

उपयोग के लिए +1 - मेरे लिए कोड का परीक्षण करना आसान हो गया। हालाँकि कोड अभी भी मल्टी-लाइन स्ट्रिंग्स के लिए काम नहीं करेगा। यदि आप आउटपुट को ध्यान से देखते हैं, तो आप देखेंगे कि किसी भी अग्रणी / अनुगामी आंतरिक स्थान को भी हटाया जा रहा है जैसे "मल्टी-लाइन" के सामने का स्थान "मल्टी-लाइन" द्वारा प्रतिस्थापित किया गया है। बस प्रत्येक पंक्ति पर अग्रणी / अनुगामी रिक्त स्थान की संख्या बढ़ाने का प्रयास करें।
गुरु

अब मैं देख रहा हूं कि आपका क्या मतलब है! सिर ऊपर करने के लिए धन्यवाद, मैंने अपना जवाब संपादित किया।
लुका बोर्रोन

@ "लुका बोर्रिएन" - आपका स्वागत है :-) क्या आप ट्रिम () में उपयोग किए जा रहे सेड सिंटैक्स की व्याख्या करेंगे? यह आपके कोड के किसी भी उपयोगकर्ता को अन्य उपयोगों के लिए इसे ट्विक करने में भी मदद कर सकता है। इसके अलावा यह नियमित अभिव्यक्ति के लिए किनारे-मामलों को खोजने में भी मदद कर सकता है।
गुरुपर्व

6

यहां एक ट्रिम () फ़ंक्शन है जो व्हाट्सएप को ट्रिम और सामान्य करता है

#!/bin/bash
function trim {
    echo $*
}

echo "'$(trim "  one   two    three  ")'"
# 'one two three'

और एक अन्य संस्करण जो नियमित अभिव्यक्ति का उपयोग करता है।

#!/bin/bash
function trim {
    local trimmed="$@"
    if [[ "$trimmed" =~ " *([^ ].*[^ ]) *" ]]
    then 
        trimmed=${BASH_REMATCH[1]}
    fi
    echo "$trimmed"
}

echo "'$(trim "  one   two    three  ")'"
# 'one   two    three'

पहला तरीका यह मुश्किल है कि यह न केवल आंतरिक व्हाट्सएप को सामान्य करता है (प्रत्येक स्थान पर व्हॉट्सएप के सभी आंतरिक स्पेस को बदलता है), बल्कि ग्लोबिंग (पथनाम विस्तार) के अधीन भी है ताकि, उदाहरण के लिए, *इनपुट स्ट्रिंग में एक चरित्र होगा वर्तमान कार्य फ़ोल्डर में सभी फ़ाइलों और फ़ोल्डरों के लिए विस्तार। अंत में, यदि $ IFS को एक नॉन-डिफॉल्ट मान पर सेट किया जाता है, तो ट्रिमिंग काम नहीं कर सकती है (हालांकि इसे जोड़कर आसानी से हटा दिया जाता है local IFS=$' \t\n')। ट्रिमिंग व्हाट्सएप के निम्नलिखित रूपों तक सीमित है: रिक्त स्थान, \tऔर \nवर्ण।
21 अप्रैल को mklement0

1
दूसरा, नियमित अभिव्यक्ति-आधारित दृष्टिकोण महान और साइड इफेक्ट-मुक्त है, लेकिन इसके वर्तमान रूप में समस्याग्रस्त है: (ए) बैश v3.2 + पर, डिफ़ॉल्ट रूप से मिलान काम नहीं करेगा, क्योंकि नियमित अभिव्यक्ति को क्रम में रखा जाना चाहिए काम करने के लिए और (बी) नियमित अभिव्यक्ति खुद उस मामले को संभालती नहीं है जहां इनपुट स्ट्रिंग एक एकल, गैर-स्थान वर्ण है जो रिक्त स्थान से घिरा हुआ है। इन समस्याओं को ठीक करने के लिए, ifलाइन को इसके साथ बदलें if [[ "$trimmed" =~ ' '*([^ ]|[^ ].*[^ ])' '* ]]:। अंत में, दृष्टिकोण केवल रिक्त स्थान से संबंधित है, न कि व्हाट्सएप के अन्य रूपों (मेरी अगली टिप्पणी देखें)।
21 अप्रैल को mklement0

2
फ़ंक्शन जो नियमित अभिव्यक्तियों का उपयोग करता है, केवल रिक्त स्थान और न ही व्हाट्सएप के अन्य रूपों से संबंधित है, लेकिन इसे सामान्य करना आसान है: ifलाइन को इसके साथ बदलें :[[ "$trimmed" =~ [[:space:]]*([^[:space:]]|[^[:space:]].*[^[:space:]])[[:space:]]* ]]
mklement0

6

AWK का उपयोग करें:

echo $var | awk '{gsub(/^ +| +$/,"")}1'

मीठा जो काम करने लगता है (उदा :) $stripped_version=इको $ वर | awk '{gsub (/ ^ + | + $ /, "")} 1'``
rogerdpack

4
सिवाय इसके कि कुछ भी नहीं किया जा रहा है: एक अनछुए वैरिएबल की गूंज पहले ही व्हॉट्सएप को हटा चुकी है
ग्लेन जैकमैन

6

असाइनमेंट प्रमुख और अनुगामी व्हाट्सएप को अनदेखा करते हैं और जैसे कि इसे ट्रिम करने के लिए इस्तेमाल किया जा सकता है:

$ var=`echo '   hello'`; echo $var
hello

8
यह सच नहीं है। यह "इको" है जो व्हाट्सएप को हटाता है, असाइनमेंट को नहीं। अपने उदाहरण में, echo "$var"रिक्त स्थान के साथ मान देखना है।
निकोलस सुस्किन

2
@ निचलोलसुस्किन एक कर सकता था var=$(echo $var)लेकिन मैं इसकी सिफारिश नहीं करता। यहां प्रस्तुत अन्य समाधान पसंद किए जाते हैं।
xebeche

5

यह अवांछित ग्लोबिंग के साथ समस्या नहीं है, साथ ही, आंतरिक सफेद-स्थान अनमॉडिफाइड है (यह मानते हुए कि $IFSडिफ़ॉल्ट पर सेट है, जो है' \t\n' )।

यह पहली नई पंक्ति (और इसे शामिल नहीं करता है) या स्ट्रिंग के अंत तक पढ़ता है, जो भी पहले आता है, और अग्रणी और अनुगामी अंतरिक्ष और \tपात्रों के किसी भी मिश्रण को दूर करता है । यदि आप कई लाइनों को संरक्षित करना चाहते हैं (और नए सिरे को पीछे छोड़ते और पीछे छोड़ते हैं), read -r -d '' var << eofइसके बजाय उपयोग करें ; हालाँकि, ध्यान दें कि यदि आपका इनपुट समाहित होता है \neof, तो यह पहले ही कट जाएगा। (सफेद स्थान के अन्य रूप, अर्थात्\r , \fऔर \v, छीन नहीं हैं , भले ही आप उन्हें $ IFS में जोड़ दें।)

read -r var << eof
$var
eof


5

यह आपके स्ट्रिंग से सभी व्हाट्सएप को हटा देगा,

 VAR2="${VAR2//[[:space:]]/}"

///स्ट्रिंग में व्हाट्सएप की पहली घटना और सभी घटनाओं को प्रतिस्थापित करता है । यानी सभी सफेद रिक्त स्थान द्वारा प्रतिस्थापित किया जाता है - कुछ भी नहीं


4

यह सबसे आसान तरीका है जिसे मैंने देखा है। यह केवल बैश का उपयोग करता है, यह केवल कुछ पंक्तियाँ है, रेगेक्सपी सरल है, और यह व्हॉट्सएप के सभी रूपों से मेल खाता है:

if [[ "$test" =~ ^[[:space:]]*([^[:space:]].*[^[:space:]])[[:space:]]*$ ]]
then 
    test=${BASH_REMATCH[1]}
fi

यहाँ इसका परीक्षण करने के लिए एक नमूना स्क्रिप्ट है:

test=$(echo -e "\n \t Spaces and tabs and newlines be gone! \t  \n ")

echo "Let's see if this works:"
echo
echo "----------"
echo -e "Testing:${test} :Tested"  # Ugh!
echo "----------"
echo
echo "Ugh!  Let's fix that..."

if [[ "$test" =~ ^[[:space:]]*([^[:space:]].*[^[:space:]])[[:space:]]*$ ]]
then 
    test=${BASH_REMATCH[1]}
fi

echo
echo "----------"
echo -e "Testing:${test}:Tested"  # "Testing:Spaces and tabs and newlines be gone!"
echo "----------"
echo
echo "Ah, much better."

1
निश्चित रूप से बेहतर है, उदाहरण के लिए (तु देवताओं!), पायथन से बाहर। सिवाय इसके कि मुझे लगता है कि स्ट्रिंग को सही ढंग से संभालने के लिए यह अधिक सरल और सामान्य है। केवल सरल अभिव्यक्ति ही होगी:^[[:space:]]*(.*[^[:space:]])?[[:space:]]*$
रॉन बर्क

4

पायथन में एक फ़ंक्शन होता है strip()जो PHP के लिए अनौपचारिक रूप से काम करता है trim(), इसलिए हम इसके लिए आसानी से समझने योग्य उपयोगिता बनाने के लिए बस थोड़ा सा इनलाइन पायथन कर सकते हैं:

alias trim='python -c "import sys; sys.stdout.write(sys.stdin.read().strip())"'

यह व्हाट्सएप की अग्रणी और अनुगामी (ट्रिमलाइन सहित) को ट्रिम कर देगा।

$ x=`echo -e "\n\t   \n" | trim`
$ if [ -z "$x" ]; then echo hi; fi
hi

जब वह काम करता है, तो आप एक समाधान की पेशकश करने पर विचार कर सकते हैं जिसमें एक स्ट्रिंग को ट्रिम करने के लिए पूर्ण अजगर इंटरप्रेटर लॉन्च करना शामिल नहीं है। यह सिर्फ बेकार है।
pdwalker 12

3
#!/bin/bash

function trim
{
    typeset trimVar
    eval trimVar="\${$1}"
    read trimVar << EOTtrim
    $trimVar
EOTtrim
    eval $1=\$trimVar
}

# Note that the parameter to the function is the NAME of the variable to trim, 
# not the variable contents.  However, the contents are trimmed.


# Example of use:
while read aLine
do
    trim aline
    echo "[${aline}]"
done < info.txt



# File info.txt contents:
# ------------------------------
# ok  hello there    $
#    another  line   here     $
#and yet another   $
#  only at the front$
#$



# Output:
#[ok  hello there]
#[another  line   here]
#[and yet another]
#[only at the front]
#[]

3

मैंने पाया कि मुझे sdiffइसे साफ करने के लिए गंदे आउटपुट से कुछ कोड जोड़ने की आवश्यकता थी :

sdiff -s column1.txt column2.txt | grep -F '<' | cut -f1 -d"<" > c12diff.txt 
sed -n 1'p' c12diff.txt | sed 's/ *$//g' | tr -d '\n' | tr -d '\t'

यह अनुगामी रिक्त स्थान और अन्य अदृश्य वर्णों को निकालता है।


हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.