අනුකූල පිළිතුර
මෙය සිදු කිරීම සඳහා විවිධ ක්රම රාශියක් ඇත bash.
කෙසේ වෙතත්, එය පළමු සටහන වැදගත් bash
වන විවිධ විශේෂ ලක්ෂණ (ඊනියා bashisms ) වෙනත් ඕනෑම වැඩ නැහැකවචය.
විශේෂයෙන්, මෙම පෝස්ට් එකේ විසඳුම් සඳහා මෙන්ම නූල් වල ඇති අනෙක් ඒවා සඳහා භාවිතා කරන අරා , සහායක අරා සහ රටා ආදේශනය , බාෂිස්වාදයන් වන අතර බොහෝ අය භාවිතා කරන වෙනත් ෂෙල් වෙඩි යටතේ ක්රියා නොකරනු ඇත.
උදාහරණයක් ලෙස: මගේ ඩේබියන් ග්නූ / ලිනක්ස් හි සම්මත කවචයක් ඇතඉර ඉර; තවත් ෂෙල් එකක් භාවිතා කිරීමට කැමති බොහෝ අය මම දනිමිksh; විශේෂ මෙවලමක් ද ඇතකාර්යබහුල පෙට්ටිය ඔහුගේම ෂෙල් පරිවර්තකය සමඟ (අළු).
ඉල්ලූ නූල
ඉහත ප්රශ්නයේදී බෙදිය යුතු නූල:
IN="bla@some.com;john@home.com"
මගේ විසඳුම සුදු අවකාශය සහිත නූල් වලට ශක්තිමත් බව සහතික කිරීම සඳහා මම මෙම නූලෙහි නවීකරණය කරන ලද අනුවාදයක් භාවිතා කරමි, එමඟින් වෙනත් විසඳුම් බිඳ දැමිය හැකිය:
IN="bla@some.com;john@home.com;Full Name <fulnam@other.org>"
දී පරිසීමකය මත පදනම්ව බෙදීම් නූල් bash (අනුවාදය> = 4.2)
දී පිරිසිදු bash
, අපි නිර්මාණය කළ හැක අරාව සඳහා තාවකාලික වටිනාකම මූලද්රව්ය සමග භේද IFS (මෙම ආදාන ක්ෂේත්රය වෙන්කර ). bash
අරාව නිර්වචනය කිරීමේදී මූලද්රව්ය අතර පරිසීමකයක් ලෙස සැලකිය යුත්තේ කුමන චරිත (ය) ද යන්න අයිඑෆ්එස් පවසයි :
IN="bla@some.com;john@home.com;Full Name <fulnam@other.org>"
# save original IFS value so we can restore it later
oIFS="$IFS"
IFS=";"
declare -a fields=($IN)
IFS="$oIFS"
unset oIFS
නවතම අනුවාද වලදී bash
, අයිඑෆ්එස් අර්ථ දැක්වීමක් සහිත විධානයක් උපසර්ග කිරීමෙන් එම විධානය සඳහා පමණක් අයිඑෆ්එස් වෙනස් වන අතර එය වහාම පෙර අගයට යලි සකසයි. මෙයින් අදහස් කරන්නේ අපට ඉහත එක පේළියකින් කළ හැකි බවයි:
IFS=\; read -a fields <<<"$IN"
# after this command, the IFS resets back to its previous value (here, the default):
set | grep ^IFS=
# IFS=$' \t\n'
අර්ධ සළකුණු මත බෙදී ඇති IN
නමක් අරාවකට ගබඩා කර ඇති බව අපට පෙනේ fields
:
set | grep ^fields=\\\|^IN=
# fields=([0]="bla@some.com" [1]="john@home.com" [2]="Full Name <fulnam@other.org>")
# IN='bla@some.com;john@home.com;Full Name <fulnam@other.org>'
(අපට මෙම විචල්යයන්ගේ අන්තර්ගතය ද ප්රදර්ශනය කළ හැකිය declare -p
:)
declare -p IN fields
# declare -- IN="bla@some.com;john@home.com;Full Name <fulnam@other.org>"
# declare -a fields=([0]="bla@some.com" [1]="john@home.com" [2]="Full Name <fulnam@other.org>")
දෙබලක හෝ බාහිර සම්පත් කැඳවීමක් නොමැති නිසා භේදය සිදු කිරීමට ඉක්මන්ම ක්රමය read
එය බව සලකන්න .
අරාව නිර්වචනය කළ පසු, ඔබට එක් එක් ක්ෂේත්රය සැකසීමට සරල පුඩුවක් භාවිතා කළ හැකිය (හෝ, ඒ වෙනුවට, ඔබ දැන් අර්ථ දක්වා ඇති අරාවේ සෑම අංගයක්ම):
# `"${fields[@]}"` expands to return every element of `fields` array as a separate argument
for x in "${fields[@]}" ;do
echo "> [$x]"
done
# > [bla@some.com]
# > [john@home.com]
# > [Full Name <fulnam@other.org>]
නැතහොත් මා කැමති මාරුවීමේ ප්රවේශයක් භාවිතයෙන් සැකසීමෙන් පසු ඔබට එක් එක් ක්ෂේත්රය අරාවෙන් ඉවත් කළ හැකිය :
while [ "$fields" ] ;do
echo "> [$fields]"
# slice the array
fields=("${fields[@]:1}")
done
# > [bla@some.com]
# > [john@home.com]
# > [Full Name <fulnam@other.org>]
ඔබට අරාවෙහි සරල මුද්රණයක් අවශ්ය නම්, ඔබට එය ඉක්මවා යාමට අවශ්ය නොවේ:
printf "> [%s]\n" "${fields[@]}"
# > [bla@some.com]
# > [john@home.com]
# > [Full Name <fulnam@other.org>]
යාවත්කාලීන කිරීම: මෑත bash > = 4.4
හි නවතම අනුවාද වලදී bash
, ඔබට විධානය සමඟ සෙල්ලම් කළ හැකිය mapfile
:
mapfile -td \; fields < <(printf "%s\0" "$IN")
මෙම වාක්ය ඛණ්ඩය විශේෂ අක්ෂර, නව රේඛා සහ හිස් ක්ෂේත්ර ආරක්ෂා කරයි!
ඔබට හිස් ක්ෂේත්ර ඇතුළත් කිරීමට අවශ්ය නැතිනම්, ඔබට පහත සඳහන් දෑ කළ හැකිය:
mapfile -td \; fields <<<"$IN"
fields=("${fields[@]%$'\n'}") # drop '\n' added by '<<<'
සමඟ mapfile
, ඔබට අරාව ප්රකාශ කිරීම මඟ හැරිය හැකි අතර, වෙන් කරන ලද මූලද්රව්යයන් මත ව්යංගයෙන් “ලූපයක්” ලබා ගත හැකිය.
myPubliMail() {
printf "Seq: %6d: Sending mail to '%s'..." $1 "$2"
# mail -s "This is not a spam..." "$2" </path/to/body
printf "\e[3D, done.\n"
}
mapfile < <(printf "%s\0" "$IN") -td \; -c 1 -C myPubliMail
(සටහන: \0
නූල් අවසානයේ හිස් ක්ෂේත්ර ගැන ඔබ තැකීමක් නොකරන්නේ නම් හෝ ඒවා නොපවතී නම්, ආකෘතියේ කෙළවරේ වැඩකට නැති ය.)
mapfile < <(echo -n "$IN") -td \; -c 1 -C myPubliMail
# Seq: 0: Sending mail to 'bla@some.com', done.
# Seq: 1: Sending mail to 'john@home.com', done.
# Seq: 2: Sending mail to 'Full Name <fulnam@other.org>', done.
නැතහොත් ඔබට භාවිතා කළ හැකි <<<
අතර, ක්රියාකාරීත්වය තුළ එය එකතු කරන නව රේඛාව අතහැර දැමීමට යම් සැකසුම් ඇතුළත් වේ:
myPubliMail() {
local seq=$1 dest="${2%$'\n'}"
printf "Seq: %6d: Sending mail to '%s'..." $seq "$dest"
# mail -s "This is not a spam..." "$dest" </path/to/body
printf "\e[3D, done.\n"
}
mapfile <<<"$IN" -td \; -c 1 -C myPubliMail
# Renders the same output:
# Seq: 0: Sending mail to 'bla@some.com', done.
# Seq: 1: Sending mail to 'john@home.com', done.
# Seq: 2: Sending mail to 'Full Name <fulnam@other.org>', done.
දී පරිසීමකය මත පදනම්ව බෙදීම් නූල් කවචය
ඔබට භාවිතා කළ නොහැකි bash
නම්, හෝ ඔබට විවිධ ෂෙල් වෙඩි භාවිතා කළ හැකි යමක් ලිවීමට අවශ්ය නම්, ඔබට බොහෝ විට bashisms භාවිතා කළ නොහැක - තවද ඉහත විසඳුම් සඳහා අප භාවිතා කළ අරා මෙයට ඇතුළත් වේ.
කෙසේ වෙතත්, නූලක “මූලද්රව්ය” ඉක්මවා යාමට අපට අරා භාවිතා කිරීමට අවශ්ය නොවේ. රටාවක පළමු හෝ අවසාන සිදුවීමෙන් නූලක උපස්ථර මකා දැමීම සඳහා බොහෝ කවච වල සින්ටැක්ස් භාවිතා වේ . *
අක්ෂර ශුන්ය හෝ වැඩි ගණනක් නියෝජනය කරන ආදේශක කාඩ්පතක් බව සලකන්න :
(මෙතෙක් පළ කර ඇති කිසිදු විසඳුමක මෙම ප්රවේශය නොමැතිකම මා මෙම පිළිතුර ලිවීමට ප්රධාන හේතුවයි;)
${var#*SubStr} # drops substring from start of string up to first occurrence of `SubStr`
${var##*SubStr} # drops substring from start of string up to last occurrence of `SubStr`
${var%SubStr*} # drops substring from last occurrence of `SubStr` to end of string
${var%%SubStr*} # drops substring from first occurrence of `SubStr` to end of string
Score_Under විසින් පැහැදිලි කළ පරිදි :
#
සහ නූල් ආරම්භයේ සහ අවසානයේ පිළිවෙලින් %
හැකි කෙටිම ගැලපෙන උපස්ථරය මකා දමන්න , සහ
##
හා %%
දිගම හැකි ගැලපෙන substring මකන්න.
ඉහත වාක්ය ඛණ්ඩය භාවිතා කරමින්, පරිමිතිය දක්වා හෝ පසුව උපස්ථරයන් මකා දැමීමෙන් අපට “මූලද්රව්ය” උපස්ථරයෙන් උපුටා ගන්නා ප්රවේශයක් නිර්මාණය කළ හැකිය.
පහත කේත අවහිරය හොඳින් ක්රියාත්මක වේ bash(මැක් ඕඑස් ඇතුළුව bash
),ඉර ඉර, ksh, සහ කාර්යබහුල පෙට්ටියගේ අළු:
IN="bla@some.com;john@home.com;Full Name <fulnam@other.org>"
while [ "$IN" ] ;do
# extract the substring from start of string up to delimiter.
# this is the first "element" of the string.
iter=${IN%%;*}
echo "> [$iter]"
# if there's only one element left, set `IN` to an empty string.
# this causes us to exit this `while` loop.
# else, we delete the first "element" of the string from IN, and move onto the next.
[ "$IN" = "$iter" ] && \
IN='' || \
IN="${IN#*;}"
done
# > [bla@some.com]
# > [john@home.com]
# > [Full Name <fulnam@other.org>]
විනෝද වන්න!