Bash විචල්‍යයකින් සුදු අවකාශය කපා ගන්නේ කෙසේද?


954

මෙම කේතය සමඟ මට ෂෙල් ස්ක්‍රිප්ට් එකක් ඇත:

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

නමුත් කොන්දේසි සහිත කේතය සැමවිටම ක්‍රියාත්මක වන්නේ hg stසෑම විටම අවම වශයෙන් එක් නව අක්ෂරයක්වත් මුද්‍රණය කරන බැවිනි .

  • $var( PHPtrim() හි මෙන් ) හිස් අවකාශය ඉවත් කිරීමට සරල ක්‍රමයක් තිබේද?

හෝ

  • මෙම ගැටළුව සමඟ කටයුතු කිරීමට සම්මත ක්‍රමයක් තිබේද?

මට sed හෝ AWK භාවිතා කළ හැකිය , නමුත් මෙම ගැටලුවට වඩාත් අලංකාර විසඳුමක් ඇතැයි මම සිතීමට කැමැත්තෙමි.


3
ආශ්‍රිත, ඔබට පූර්ණ සංඛ්‍යාවක් මත ඉඩ අඩු කර පූර්ණ සංඛ්‍යාවක් ලබා ගැනීමට අවශ්‍ය නම්, $ (($ var)) සමඟ ඔතා, ද්විත්ව උපුටා දැක්වීම් තුළ පවා එය කළ හැකිය. මම දිනය ප්‍රකාශය සහ ගොනු නාම භාවිතා කරන විට මෙය වැදගත් විය.
වොලොමයික්

"මෙම ගැටළුව සමඟ කටයුතු කිරීමට සම්මත ක්‍රමයක් තිබේද?" ඔව්, [[වෙනුවට [. $ var=$(echo) $ [ -n $var ]; echo $? #undesired test return 0 $ [[ -n $var ]]; echo $? 1
user.friendly

එය උදව් කරන්නේ නම්, අවම වශයෙන් එය උබුන්ටු 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';
bruziuz

Answers:


1046

ප්‍රමුඛ, පසුපස හා අතරමැදි සුදු අවකාශය අඩංගු විචල්‍යයක් නිර්වචනය කරමු:

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

(නිර්වචනයක් සියලු whitespace ඉවත් කරන්නේ කොහොමද [: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

ප්‍රමුඛ හා පසුපස අවකාශ දෙකම ඉවත් කරන්නේ කෙසේද - දම්වැල sed:

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ප්‍රවේශය ක්‍රියාත්මක වන්නේ තනි පේළි ආදානය මත පමණක් බව සලකන්න . බහු-පේළි ආදානය සමඟ ක්‍රියා කරන සහ බාෂ්ගේ සාදන ලද විශේෂාංග භාවිතා කරන ප්‍රවේශයන් සඳහා, @ බෂ්ෆු සහ ur ගුරුම්ගේ පිළිතුරු බලන්න. Ich නිකලස් සුෂ්කින්ගේ විසඳුමේ සාමාන්‍යකරණය වූ පේළිගත අනුවාදය මේ වගේ ය: trimmed=$([[ " test test test " =~ [[:space:]]*([^[:space:]]|[^[:space:]].*[^[:space:]])[[:space:]]* ]]; echo -n "${BASH_REMATCH[1]}")
mklement0

7
ඔබ බොහෝ විට එසේ කරනවා නම්, appending 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/'. එය ප්‍රමුඛ හා පසුපස සුදු අවකාශය කපා හරින අතර, සුදු පැහැති අවකාශයෙන් වෙන් වූ ඕනෑම අනුපිළිවෙලක් මධ්‍යයේ ඇති සුදු පැහැති නොවන අක්ෂර ග්‍රහණය කරයි. විනෝද වන්න!
වික්ටර් සාමනියන්

IctVictorZamanian ආදානයේ අඩංගු වන්නේ හිස් අවකාශයක් නම් ඔබේ විසඳුම ක්‍රියාත්මක නොවේ. MattyV විසින් සපයන ලද රටා දෙකේ sed විසඳුම් සහ නිදසුනක් ලෙස මා හට සුදු අවකාශය පමණක් ආදානය සමඟ හොඳින් ක්‍රියා කරයි.
ටෝර්බන්

Or ටෝර්බන් ෆෙයාර් පොයින්ට්. තනි ප්‍රකාශනය කොන්දේසි |කිහිපයකට වඩා කොන්දේසි සහිතව කළ හැකි යැයි මම සිතමි .
වික්ටර් සාමනියන්

1027

සරල පිළිතුරක් නම්:

echo "   lol  " | xargs

Xargs ඔබ වෙනුවෙන් කැපීම කරනු ඇත. එය එක් විධානයක් / වැඩසටහනකි, පරාමිතීන් නොමැත, කැපූ නූල නැවත ලබා දෙයි, එය පහසුය!

සටහන: මෙය සියලු අභ්‍යන්තර අවකාශයන් ඉවත් නොකරන බැවින් "foo bar"එක හා සමාන වේ; එය බවට පත් නොවේ "foobar". කෙසේ වෙතත්, බහු අවකාශයන් තනි අවකාශයන්ට ensed නීභවනය වන බැවින් "foo bar"එය බවට පත්වේ "foo bar". ඊට අමතරව එය පේළි අක්ෂරවල අවසානය ඉවත් නොකරයි.


27
හොඳයි. මෙය ඉතා හොඳින් ක්‍රියාත්මක වේ. මම xargs echoකරන්නේ කුමක්ද යන්න පිළිබඳව වාචිකව කථා කිරීමට එය නල කිරීමට මම තීරණය කර ඇත්තෙමි , නමුත් xargs ස්වකැමැත්තෙන් පෙරනිමියෙන් echo භාවිතා කරනු ඇත.
විල්

24
කදිම උපක්‍රමයක්, නමුත් ප්‍රවේශම් වන්න, ඔබට එය එක් පේළියක් සඳහා භාවිතා කළ හැකි නමුත් xargs සැලසුම මඟින් - එය බහු-පේළි පයිප්ප අන්තර්ගතයෙන් කැපීම පමණක් නොකරනු ඇත. sed එවිට ඔබේ මිතුරා ය.
ජොසලින් ඩෙලලන්ඩ්

23
Xargs හි ඇති එකම ගැටළුව වන්නේ එය නව රේඛාවක් හඳුන්වා දීමයි, ඔබට නව රේඛාව නවතා දැමීමට අවශ්‍ය නම් sed 's/ *$//'විකල්පයක් ලෙස මම නිර්දේශ කරමි . ඔබ දකින්න පුළුවන් xargsමේ වගේ නව පේළියකට යොමු කිරීමේ අක්ෂරය: echo -n "hey thiss " | xargs | hexdump ඔබ ඒ දෙස 0a73aඑම නව පේළියකට යොමු කිරීමේ අක්ෂරය වේ. ඔබත් එසේ කරන්නේ නම් sed: echo -n "hey thiss " | sed 's/ *$//' | hexdumpඔබට පෙනෙනු ඇත 0073, නව රේඛාවක් නොමැත.

8
ප්රවේශම් සහගත; Xargs වෙත නූල අතර අතිරික්ත අවකාශයන් තිබේ නම් මෙය තදින් කැඩී යනු ඇත. "මෙය එක් තර්කයක්" වැනි. xargs හතරකට බෙදේ.
බොස්

65
මේක නරකයි. 1. එය බවට a<space><space>bපත්වේ a<space>b. 2. ඊටත් වඩා: එය බවට a"b"c'd'eපත්වේ abcde. 3. ඊටත් වඩා: එය අසාර්ථක වනු ඇත a"b, ආදිය
සාෂා

375

ආදේශකයක් ලෙස හැඳින්වෙන Bash බිල්ට්-ඉන්ස් පමණක් භාවිතා කරන විසඳුමක් තිබේ :

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- අනුකූල කවචයක් සමඟ ක්‍රියා කරනු ඇත.

යොමුව


19
දක්ෂයි! මෙය මගේ ප්‍රියතම විසඳුම වන අතර එය ගොඩනංවන ලද බාෂ් ක්‍රියාකාරිත්වය භාවිතා කරයි. පළ කිරීම ගැන ස්තූතියි! An සාන්, එය කැදැලි නූල් දෙකකි. උදා, s=" 1 2 3 "; echo \""${s%1 2 3 }"\"සෑම දෙයක්ම අවසානයේ සිට කපා දමනු ඇත " ". Subbing 1 2 3 සමග [![:space:]]*"clobber එය එසේ නම්, පළමු නොවන අවකාශය චරිතය සොයා හා පසුව සෑම දෙයක්ම" එය පවසනවා. %%ඒ වෙනුවට භාවිතා කිරීමෙන් %කප්පාදුවේ සිට කෙළවරේ ක්‍රියාකාරිත්වය කෑදර වේ. මෙය ආරම්භයේ සිටම කෑදර නොවන ටිම් එකක කූඩු කර ඇත, එබැවින් ඇත්ත වශයෙන්ම ඔබ " "මුල සිටම කපයි. අවසාන අවකාශයන් සඳහා%, #, සහ * මාරු කරන්න. බාම්!
මාර්ක් ජී.

2
මට අනවශ්‍ය අතුරු ආබාධ කිසිවක් හමු වී නැති අතර ප්‍රධාන කේතය අනෙකුත් පොසික්ස් වැනි ෂෙල් වෙඩි සමඟද ක්‍රියා කරයි. කෙසේ වෙතත්, සොලාරිස් 10 යටතේ, එය සමඟ ක්‍රියා නොකරයි /bin/sh(සමඟ පමණක් /usr/xpg4/bin/sh, නමුත් මෙය සුපුරුදු sh ස්ක්‍රිප්ට් සමඟ භාවිතා නොකරනු ඇත).
vinc17

9
Sed, tr යනාදිය භාවිතා කිරීමට වඩා හොඳ විසඳුමක්, එය වඩා වේගවත් බැවින්, ඕනෑම දෙබලක () වළක්වා ගන්න. සිග්වින් හි වේගයෙහි වෙනස විශාලත්වයේ අනුපිළිවෙලකි.
ජීන් පැව්ලොව්ස්කි

9
An සාන් මුලදී මම කඩුල්ලේ රැඳී සිටියේ මේවා නිත්‍ය ප්‍රකාශන යැයි සිතූ බැවිනි. ඒගොල්ලො නෙමෙයි. ඒ වෙනුවට, මෙම රටාව ගැලපීම් කාරක රීති (වේ gnu.org/software/bash/manual/html_node/Pattern-Matching.html , wiki.bash-hackers.org/syntax/pattern ) ඉවත් කිරීම (Substring භාවිතා tldp.org/LDP/abs /html/string-manipulation.html ). එබැවින් ${var%%[![:space:]]*}" varඅභ්‍යවකාශ නොවන අක්ෂරයකින් ආරම්භ වන එහි දිගම උපස්ථරයෙන් ඉවත් කරන්න" යනුවෙන් පවසයි . එයින් අදහස් වන්නේ ඔබ ඉතිරිව ඇත්තේ ඔබ පසුව ඉවත් කරන ප්‍රමුඛ අවකාශය (ය) සමඟ පමණක් ${var#..බවයි. පහත දැක්වෙන රේඛාව (පසුපස) ප්‍රතිවිරුද්ධයයි.
ඔහාඩ් ෂ්නයිඩර්

12
මෙය අතිමහත් පරිපූර්ණ විසඳුමයි. එකක් හෝ ඊට වැඩි බාහිර ක්රියාවලිය (උදා: ෆොර්කින් awk, sed, tr, xargsතනි string සිට) හුදෙක් ටිම් whitespace මූලිකව උමතු වේ - බොහෝ ෂෙල් වෙඩි (bash ඇතුළුව), විශේෂයෙන් විට දැනටමත් සිදු-of-the-කොටුව දේශීය සංගීත munging පහසුකම් ලබා දෙයි.
සිසිල් කරි

82

Bash හි පරාමිති ප්‍රසාරණය යනුවෙන් හැඳින්වෙන අංගයක් ඇති අතර, වෙනත් දේ අතර ඊනියා රටා මත පදනම්ව නූල් ප්‍රතිස්ථාපනය කිරීමට ඉඩ ලබා දේ (රටා නිත්‍ය ප්‍රකාශන වලට සමාන ය, නමුත් මූලික වෙනස්කම් හා සීමාවන් ඇත). [flussence හි මුල් පේළිය: Bash හි නිත්‍ය ප්‍රකාශන ඇත, නමුත් ඒවා හොඳින් සැඟවී ඇත:]

පහත දැක්වෙන්නේ විචල්‍ය අගයකින් සියලු සුදු අවකාශය (අභ්‍යන්තරයෙන් පවා) ඉවත් කරන්නේ කෙසේද යන්නයි .

$ 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 මධ්‍යයේ ඇති අවකාශයන් සඳහා ක්‍රියා කරයි, නමුත් මම අවසානයේ එය නැංගුරම් දැමීමට උත්සාහ කරන විට නොවේ.
පෝල් ටොම්බ්ලින්

මෙය කිසියම් උදව්වක් කරයිද? මෑන් පිටුවෙන්: "$ {පරාමිතිය / රටාව / නූල්} [...] රටාව% සමඟ ආරම්භ වන්නේ නම්, එය පරාමිතියේ පුළුල් කළ අගය අවසානයේ අනුරූප විය යුතුය."

Nt ඒ නිසා ඒවා සාමාන්‍ය ප්‍රකාශන නොවේ, නමුත් ඒ හා සමාන දෙයක්ද?
පෝල් ටොම්බ්ලින්

3
ඒවා රීජෙක්ස්, අමුතු උපභාෂාවක්.

13
${var/ /}පළමු අභ්‍යවකාශ අක්‍ෂරය ඉවත් කරයි. ${var// /}සියලුම අභ්‍යවකාශ අක්ෂර ඉවත් කරයි. මෙම ඉදිකිරීමෙන් පමණක් ප්‍රමුඛ හා පසුපස හිස් අවකාශය කැපීමට ක්‍රමයක් නොමැත.
ගිලෙස්ගේ SO- නපුරු වීම නවත්වන්න '

62

නූලක ආරම්භයේ සහ අවසානයේ සිට සියලු අවකාශයන් ඉවත් කිරීම සඳහා (රේඛා අක්ෂරවල අවසානය ඇතුළුව):

echo $variable | xargs echo -n

මෙය අනුපිටපත් අවකාශයන් ද ඉවත් කරයි:

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

නිෂ්පාදනය කරයි: 'මෙම නූලට විශාල ඉඩ ප්‍රමාණයක් ඇත'


5
මූලික වශයෙන් xargs සියළුම පරිසීමක නූලෙන් ඉවත් කරයි. පෙරනිමියෙන් එය අවකාශය පරිසීමකය ලෙස භාවිතා කරයි (මෙය -d විකල්පය මගින් වෙනස් කළ හැකිය).
rkachach

4
මෙය බොහෝ දුරට පිරිසිදු (කෙටි හා කියවිය හැකි) විසඳුමයි.
පොතර්කා

ඔබට echo -nකිසිසේත් අවශ්‍ය ඇයි ? echo " my string " | xargsඑකම ප්‍රතිදානය ඇත.
bfontaine

echo -n රේඛාවේ අවසානයද ඉවත් කරයි
rkachach

56

එක් ප්‍රමුඛ හා පසුපස ස්ථානයක් ඉවත් කරන්න

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 අක්ෂර පමණක් සීමා කරයි. එබැවින් ප්‍රතිරාවය ප්‍රති results ල වේ'hello world ', 'foo bar', 'both sides '
ජෝ

O ජෝ මම මීට වඩා හොඳ විකල්පයක් එක් කළෙමි.
wjandrea

43

මත බෑෂ් මාර්ගෝපදේශය අංශයෙන් globbing

පරාමිති ප්‍රසාරණයක දී 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
ඔබ නිරීක්ෂණය කළ පරිදි ටිම් () ප්‍රමුඛ හා පසුපස සුදු අවකාශය පමණක් ඉවත් කරයි.
ගුරු

Mkelement දැනටමත් සටහන් කර ඇති පරිදි, ඔබ ශ්‍රිත පරාමිතිය $ (ටිම් $ string) වෙනුවට උපුටා ගත් නූලක් ලෙස සම්මත කළ යුතුය. නිවැරදි භාවිතය පෙන්වීමට මම කේතය යාවත්කාලීන කර ඇත. ස්තූතියි.
ගුරු

ෂෙල් විකල්ප ගැන දැන ගැනීම මා අගය කරන තරමට, රටා ආදේශක 2 ක් කරනවාට වඩා අවසාන
ප්‍රති result ලය

(Bash හි මෑත කාලීන අනුවාදයක් සමඟ), විකල්පය ප්‍රතිෂ් oring ාපනය කිරීමේ යාන්ත්‍රණය extglobභාවිතා කිරීමෙන් ඔබට සරල කළ හැකි බව සලකන්න shopt -p: local restore="$(shopt -p extglob)" ; shopt -s extglobඔබේ ශ්‍රිතයේ ආරම්භයේදීම ලියන්න , සහ eval "$restore"අවසානයේ දී (හැර, ප්‍රදානය කිරීම හැර, නපුර…).
Maëlan

විශිෂ්ට විසඳුමක්! එක් විභව වැඩිදියුණු කිරීමක්: එය [[:space:]]අවකාශයක් සමඟ ප්‍රතිස්ථාපනය කළ හැකි බව පෙනේ : ${var##+( )}එසේම ${var%%+( )}වැඩ කරන අතර ඒවා කියවීමට පහසු වේ.
ඩීක්‍රූට්

41

ඔබට මෙය සරලව කපා ගත හැකිය 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"... පුදුමයි! එපමණක් නොව මෙය එකිනෙකට පරස්පර අවකාශයන් එකකට කඩා වැටේ.
gniourf_gniourf

5
ඔබ නම් මෙය කදිම විසඳුමකි: 1. කෙළවරේ කිසිදු ඉඩක් අවශ්‍ය නැත 2. එක් එක් වචනය අතර එක් ඉඩක් පමණක් අවශ්‍ය වේ 3. පාලක ආදානය සමඟ ආදේශක කාඩ්පත් නොමැතිව ක්‍රියා කරයි. එය අත්‍යවශ්‍යයෙන්ම නරක ලෙස ආකෘතිගත කළ ලැයිස්තුවක් හොඳ එකක් බවට පත් කරයි.
musicin3d

ආදේශක කාඩ්පත් පිළිබඳ හොඳ මතක් කිරීමක් @gniourf_gniourf +1. තවමත් විශිෂ්ට විසඳුමක් වන වැම්ප්. ඔබටත් +1 කරන්න.
ආචාර්ය බෙකෝ

25

මම හැම විටම එය sed සමඟ කර ඇත

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

වඩාත් අලංකාර විසඳුමක් තිබේ නම්, කවුරුහරි එය පළ කරනු ඇතැයි මම බලාපොරොත්තු වෙමි.


ඔබට වාක්‍ය ඛණ්ඩය පැහැදිලි කළ sedහැකිද?
farid99

2
නිත්‍ය ප්‍රකාශනය සියලු පසුපස සුදු අවකාශයට ගැලපෙන අතර එය කිසිවක් නොමැතිව ප්‍රතිස්ථාපනය කරයි.
පෝල් ටොම්බ්ලින්

4
ප්‍රමුඛ සුදු අවකාශයන් ගැන කුමක් කිව හැකිද?
ක්වාන් චෙන්

මෙය සියලු පසුපස සුදු අවකාශය ඉවත් sed -e 's/\s*$//'කරයි. පැහැදිලි කිරීම: 's' යන්නෙන් සෙවීම, '\ s' යන්නෙන් සියලු සුදු අවකාශය, '*' යන්නෙන් අදහස් කරන්නේ ශුන්‍ය හෝ බොහෝ ය, '$' යන්නෙන් අදහස් වන්නේ රේඛාවේ අවසානය දක්වා වන අතර '//' යන්නෙන් අදහස් කරන්නේ සියලුම තරග හිස් නූලකින් ආදේශ කිරීමයි .
ක්‍රේග්

'S / * $ //' හි, එක් ඉඩක් වෙනුවට තරු ලකුණු කිරීමට පෙර අවකාශ 2 ක් ඇත්තේ ඇයි? එය අක්ෂර වින්‍යාසයක්ද?
බ්‍රෙන්ට් 212


24

Bash හි දීර් pattern රටා ගැලපුම් අංග සක්‍රිය කර ඇති විට ( shopt -s extglob), ඔබට මෙය භාවිතා කළ හැකිය:

{trimmed##*( )}

අත්තනෝමතික ප්‍රමුඛ අවකාශයන් ඉවත් කිරීමට.


භයානකයි! මම හිතන්නේ මෙය වඩාත්ම සැහැල්ලු හා අලංකාර විසඳුමයි.
dubiousjim

1
(අ) සියලු ආකාරයේ සුදු අවකාශයන් සමඟ කටයුතු කරන සහ (ආ) සුදු අවකාශය පසුපස හඹා යන සමාන, නමුත් වඩාත් ජනක විසඳුමක් සඳහා පහත @ ගුරුම්ගේ ලිපිය බලන්න .
mklement0

මගේ කේත ස්නිපටය ශ්‍රිතයක් ලෙස නැවත ලිවීමට කරදර කිරීම සඳහා kmkelement +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
අරුම පුදුම! සරල හා effective ලදායී! පැහැදිලිවම මගේ ප්‍රියතම විසඳුම. ඔබට ස්තුතියි!
xebeche

1
RaCraigMcQueen එය විචල්ය අගය වන අතර readඑහි නම $ 1 මගින් එහි අගය අනුව අඩු කළ අනුවාදයක් ගබඩා කරයි $ {! 1}
Aquarius Power

2
ටිම් () ශ්‍රිතයේ පරාමිතිය විචල්‍ය නාමයකි: test_trim () තුළ () ටිම් කිරීමට ඇමතුම බලන්න. Test_trim () වෙතින් කැඳවූ පරිදි ටිම් () තුළ, $ 1 foo දක්වාත් $ {! 1} $ foo දක්වාත් (එනම් විචල්‍ය foo හි වත්මන් අන්තර්ගතයන් දක්වා) පුළුල් වේ. 'විචල්ය ඉන්ඩිරෙක්ෂන්' සඳහා bash අත්පොත සොයන්න.
flabdablet

1
එක් ඇමතුමකින් බහුවිධ විචල්‍යයන් කැපීමට සහාය වීම සඳහා මෙම කුඩා වෙනස් කිරීම ගැන කුමක් කිව හැකිද? trim() { while [[ $# -gt 0 ]]; do read -rd '' $1 <<<"${!1}"; shift; done; }
ජීන් පැව්ලොව්ස්කි

2
Qu ඇක්වාරියස් පවර් එක්-ලයිනර් අනුවාදය සඳහා උප කුලකයක echo භාවිතා කිරීමේ අවශ්‍යතාවයක් නොමැත 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

ondleondepeon ඔබ මෙය උත්සාහ කළාද? මම එය ලියා නැවත උත්සාහ කළ විට මම උත්සාහ කළෙමි, ඔබේ යෝජනාව කිසිදු බාෂ්, ඩෑෂ්, කාර්යබහුල පෙට්ටියක ක්‍රියාත්මක නොවේ
ඩැනියෙල් ඇල්ඩර්

An ඩැනියෙල් ඇල්ඩර් මම කළා, නමුත් එය දැනටමත් වසර 3 කට පෙර මෙන්, මම එය භාවිතා කළ කේතය සොයාගත නොහැක. කෙසේ වෙතත්, දැන් මම [[:space:]]වෙනත් පිළිතුරක් මෙන් භාවිතා කරමි : stackoverflow.com/a/3352015/3968618
leondepeon

11

ඔබට පැරණි පාසල භාවිතා කළ හැකිය tr. නිදසුනක් ලෙස, මෙය git ගබඩාවක නවීකරණය කරන ලද ගොනු ගණන නැවත ලබා දෙයි.

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>

එකම ප්‍රති result ලය සඳහා එය අඩු රේඛා මත තැබීමට:

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

1
මට වැඩ කළේ නැහැ. පළමුවැන්න මුද්‍රණය නොකළ නූල් මුද්‍රණය කළේය. දෙවැන්න නරක ආදේශකයක් විසි කළේය. මෙහි සිදුවන්නේ කුමක්ද යන්න ඔබට පැහැදිලි කළ හැකිද?
musicin3d

1
@ musicin3d: මම මේ වාර සිදු නොවන බව ද නිතර භාවිතා පිවිසෙන වෙබ් අඩවිය හැසිරවීම bash වැඩ විචල්ය සඳහා සොයන්න ${var##Pattern}වැඩි විස්තර සඳහා. එසේම, මෙම වෙබ් අඩවිය බැෂ් රටා පැහැදිලි කරයි . එබැවින් ##මාධ්‍යයන් විසින් ලබා දී ඇති රටාව ඉදිරිපසින් %%ඉවත් කර, ලබා දී ඇති රටාව පිටුපසින් ඉවත් කරන්න. මෙම +( )කොටස රටාව වන අතර, එය, "එක් හෝ හිස් ඉඩක් තවත් සිදුවීමක්" යන්නයි
gMale

හාස්‍යජනකයි, එය ක්ෂණිකව ක්‍රියාත්මක විය, නමුත් bash ස්ක්‍රිප්ට් ගොනුවට මාරු කිරීමෙන් පසුව නොවේ.
ආචාර්ය බෙකෝ

අමුතුයි. අවස්ථා දෙකේදීම එකම බැෂ් අනුවාදයද?
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")")"
}

9

AWK භාවිතා කරන්න:

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

වැඩ කරන බව පෙනෙන මිහිරි (උදා :) $stripped_version=echo $ var | awk 's gsub (/ ^ + | + $ /, "")} 1'``
rogerdpack

4
අවදි වීම හැර කිසිවක් නොකරයි: නම් නොකල විචල්‍යයක් ප්‍රතිරාවය කිරීම දැනටමත්
සුදු අවකාශය

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විචල්‍යයේ අගය අඩු නොකෙරේ.
සීසර්සෝල්

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

1
වචන දෙකක් අතර ඉඩ එකකට වඩා තිබේ නම් එය ක්‍රියා නොකරනු ඇත. උත්සාහ කරන්න: echo $(echo "1 2 3")(1, 2 සහ 3 අතර අවකාශ දෙකක් සහිතව).
joshlf

7

මම සරලවම sed භාවිතා කරමි:

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

a) තනි පේළියේ භාවිතා කිරීමේ උදාහරණය

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
}'

සටහන: kmkelement විසින් යෝජනා කර ඇති පරිදි එය බහු රේඛා නූල් සඳහා ක්‍රියා නොකරනු ඇත, නමුත් එය තනි රේඛා නූල් සඳහා වැඩ කළ යුතුය.
ගුරු

1
ඔබ වැරදියි: එය බහු රේඛා නූල් මත ද ක්‍රියා කරයි. එය අත්හදා බලන්න! :)
ලූකා බෝරියන්

භාවිතය සඳහා +1 - කේතය පරීක්ෂා කිරීම මට පහසු කර ඇත. කෙසේ වෙතත් කේතය තවමත් බහු රේඛා නූල් සඳහා ක්‍රියා නොකරයි. ඔබ ප්‍රතිදානය දෙස හොඳින් බැලුවහොත්, ඕනෑම ප්‍රමුඛ / පසුපස අභ්‍යන්තර අවකාශයන්ද ඉවත් වෙමින් පවතින බව ඔබට පෙනෙනු ඇත. උදා: “බහු රේඛාව” ඉදිරිපිට ඇති අවකාශය “බහු රේඛාව” මගින් ප්‍රතිස්ථාපනය වේ. එක් එක් පේළියේ ප්‍රමුඛ / පසුපස අවකාශ ගණන වැඩි කිරීමට උත්සාහ කරන්න.
ගුරු

ඔබ අදහස් කරන දේ දැන් මට පෙනේ! හිස ඔසවා තැබීමට ස්තූතියි, මම මගේ පිළිතුර සංස්කරණය කළෙමි.
ලූකා බෝරියන්

Lu "ලූකා බෝරියන්" - සාදරයෙන් පිළිගනිමු :-) ඔබ ටිම් () හි භාවිතා කරන sed වාක්‍ය ඛණ්ඩය පැහැදිලි කරනවාද? එය ඔබගේ කේතයේ ඕනෑම පරිශීලකයෙකුට වෙනත් භාවිතයන් වෙත වෙනස් කිරීමට උපකාරී වේ. නිත්‍ය ප්‍රකාශනය සඳහා අද්විතීය අවස්ථා සොයා ගැනීමට පවා එය උදව් වනු ඇත.
ගුරු

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අක්ෂර.
mklement0

1
දෙවන, නිත්‍ය ප්‍රකාශන මත පදනම් වූ ප්‍රවේශය විශිෂ්ට සහ අතුරු ආබාධ රහිත ය, නමුත් එහි වර්තමාන ස්වරූපයෙන් ගැටළු සහගත ය: (අ) bash v3.2 + මත, ගැලපීම පෙරනිමියෙන් ක්‍රියා නොකරනු ඇත, මන්ද නිත්‍ය ප්‍රකාශනය අනුපිළිවෙලින් සඳහන් කළ යුතු නොවේ වැඩ කිරීමට සහ (ආ) නිත්‍ය ප්‍රකාශනය මඟින් ආදාන දාමය අවකාශයන්ගෙන් වට වූ තනි, අවකාශ නොවන චරිතයක් වන අවස්ථාව හසුරුවන්නේ නැත. මෙම ගැටළු නිරාකරණය කිරීම සඳහා, ifරේඛාව ආදේශ කරන්න : if [[ "$trimmed" =~ ' '*([^ ]|[^ ].*[^ ])' '* ]]. අවසාන වශයෙන්, ප්‍රවේශය ගනුදෙනු කරන්නේ අවකාශයන් සමඟ මිස වෙනත් අවකාශයන් සමඟ නොවේ (මගේ ඊළඟ අදහස බලන්න).
mklement0

2
නිත්‍ය ප්‍රකාශන භාවිතා කරන ශ්‍රිතය ගනුදෙනු කරන්නේ අවකාශයන් සමඟ මිස වෙනත් සුදු අවකාශයක් සමඟ නොවේ, නමුත් සාමාන්‍යකරණය කිරීම පහසුය: ifරේඛාව ආදේශ කරන්න :[[ "$trimmed" =~ [[:space:]]*([^[:space:]]|[^[:space:]].*[^[:space:]])[[:space:]]* ]]
mklement0

6

මෙය ඔබගේ සංගීතයෙන් සියලු සුදු අවකාශයන් ඉවත් කරනු ඇත,

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

/පළමු සිදුවීම සහ //සුදු පැහැති අවකාශයේ සියලු සිදුවීම් ප්‍රතිස්ථාපනය කරයි . එනම් සියලු සුදු අවකාශයන් ප්‍රතිස්ථාපනය වේ - කිසිවක් නැත


6

පැවරුම් ප්‍රමුඛ හා පසුපස සුදු අවකාශය නොසලකා හරින අතර ඒවා කැපීමට භාවිතා කළ හැකිය:

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

8
එය සත්‍යයක් නොවේ. එය "ප්‍රතිරාවය" වන්නේ අවකාශය ඉවත් කිරීම මිස පැවරුම නොවේ. ඔබේ උදාහරණයේ දී, echo "$var"අවකාශය සමඟ වටිනාකම බැලීමට කරන්න.
නිකලස් සුෂ්කින්

2
IchNicholasSushkin One හට කළ හැකි 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


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

4

එක් අවකාශයකට අවකාශය ඉවත් කිරීම:

(text) | fmt -su

3

මෙය ඉදිරිපස සහ කෙළවරේ බහු අවකාශයන් කපා දමයි

whatever=${whatever%% *}

whatever=${whatever#* }


7
ඔබගේ දෙවන විධානය අනුමාන වශයෙන් ##පමණක් තිබිය යුතුය #. නමුත් ඇත්ත වශයෙන්ම මේවා ක්‍රියාත්මක නොවේ. ඔබ තරඟ අවකාශය ලබා දෙනවා රටාව අනුගමනය ඕනෑම 0 ක් හෝ ඊට වැඩි අවකාශ අනුක්රමයක් නැහැ, තවත් චරිත අනුපිළිවෙල. එය *ෂෙල් ග්ලෝබින් *මිස සුපුරුදු "0-හෝ ඊට වැඩි" රීජෙක්ස් නොවේ *.
dubiousjim

1
නූලෙහි කිසිදු ඉඩක් නොමැති බව ඔබ දන්නේ නම් මේවා ප්‍රයෝජනවත් වේ. ඔවුන් පත් කිරීම සඳහා වූ විශාල වැඩ " foo "කිරීමට "foo". මක්නිසාද යත් " hello world ", එතරම් නොවේ.
ජේඩී

t=" "" a "" "; echo "=${t#* }="ප්‍රතිදානය = a =ප්‍රමුඛ බහු අවකාශයන් ඉවත් නොකෙරේ. t=" "" a "" "; echo "=${t%% *}="නිමැවුම් ==පසුපස අවකාශය නූල් අන්තර්ගතයෙන් ඉවත් කරනු ලැබේ. (SE නිසා ද්විත්ව උපුටා දැක්වීම.)
catpnosis

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]
#[]
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.