සියළුම තර්ක බාෂ් ෂෙල් පිටපතකින් ප්‍රචාරණය කරන්න


880

මම ලියන්නේ ඉතා සරල පිටපතක් වෙනත් පිටපතක් ලෙස හඳුන්වන අතර, මගේ වර්තමාන පිටපතේ සිට මා ක්‍රියාත්මක කරන පිටපත දක්වා පරාමිතීන් ප්‍රචාරය කළ යුතුය.

උදාහරණයක් ලෙස, මගේ ස්ක්‍රිප්ට් නම foo.shසහ ඇමතුම්bar.sh

foo.sh:

bar $1 $2 $3 $4

එක් එක් පරාමිතිය පැහැදිලිව සඳහන් නොකර මා මෙය කරන්නේ කෙසේද?



මෙයද බලන්න stackoverflow.com/questions/12314451/...
Vadzim

Answers:


1454

ඔබේ පරාමිතීන් එලෙසම සම්මත කර ගැනීමට ඔබ කැමති නම් "$@"සරල වෙනුවට භාවිතා කරන්න $@.

නිරීක්ෂණය කරන්න:

$ cat foo.sh
#!/bin/bash
baz.sh $@

$ cat bar.sh
#!/bin/bash
baz.sh "$@"

$ cat baz.sh
#!/bin/bash
echo Received: $1
echo Received: $2
echo Received: $3
echo Received: $4

$ ./foo.sh first second
Received: first
Received: second
Received:
Received:

$ ./foo.sh "one quoted arg"
Received: one
Received: quoted
Received: arg
Received:

$ ./bar.sh first second
Received: first
Received: second
Received:
Received:

$ ./bar.sh "one quoted arg"
Received: one quoted arg
Received:
Received:
Received:

8
මෙය උපුටා ගත් / පැන ගිය නූල් හරහා පිරිසිදු ලෙස ගමන් කිරීම සඳහා මෙය සිදු කරයි: නිරීක්ෂණය කරන්න: cat rsync_foo.sh #! / Bin / bash echo "$ @" rsync "$ @" ./rsync_foo.sh -n "bar me" bar2 bar me bar2skipping directory bar me සත්‍ය මුල් විධාන රේඛාව උපුටා දැක්වීම් හෝ ගැලවී ගිය නූල් වලින් සම්පූර්ණ ලෙස දැකිය හැකි ෂෙල් ස්ක්‍රිප්ට් තිබිය හැකිද?
මාර්ක් එඩින්ටන්

3
කොඩි පසු කිරීම ගැන කුමක් කිව හැකිද? උදා, './bar.sh --with-stuff'
නේතන් ලෝන්ග්

5
වචන බෙදීමේ විෂය වඩා හොඳින් තේරුම් ගැනීමට කැමති ඕනෑම කෙනෙකුට ඒ ගැන වැඩි විස්තර මෙතැනින් කියවීමට
Rany Albeg Wein

4
'arg with spaces'උදාහරණ තුන සඳහා ඇතුළත් කළ විට කුමක් සිදුවේදැයි පෙන්වීමට මම යෝජනා කරමි . ප්‍රති results ල ගැන මා පුදුමයට පත් විය; ඔබට ඒවා පැහැදිලි කළ හැකිය.
මයිකල් ෂෙපර්

2
@MichaelScheper, අවාසනාව, ./foo.sh "arg with spaces"සහ ./foo.sh 'arg with spaces'මම දෙන ලද උදාහරන එය එකතු කිරීම සඳහා වූ යෝජනාව කිසිදු උදව් වනු ඇත ආකාරය නැහැ ඒ නිසා, 100% ක් සමාන වේ.
චාල්ස් ඩෆි

476

සඳහා bash සහ අනෙකුත් Bourne-වැනි කවච:

java com.myserver.Program "$@"

13
M අමීර්: නැත, csh සඳහා නොවේ . සෑම කෙනෙකුගේම සිහිබුද්ධිය සඳහා: csh ස්ක්‍රිප්ට් නොකරන්න . නමුත් මම හිතන්නේ සමහර විට $argv:qසමහර csh ප්‍රභේදවල ක්‍රියා කරනු ඇත.
ක්‍රිස් ජොන්සන්

2
ස්තූතියි! අපේක්ෂිත පරිදි, මෙය ස්ක්‍රිප්ටයට ලැබුණු එකම තර්ක මාලාවක් පසු කරයි - එක් විශාල තර්කයක් නොවේ. ද්විත්ව උපුටා දැක්වීම් අවශ්ය වේ. අවකාශයන් ඇතුළත් උපුටා දැක්වීම් සමඟ වුවද ක්‍රියා කරයි.
ඇන්ඩි තෝමස්

26
ආශ්‍රිත: ඔබේ ෂෙල් ස්ක්‍රිප්ට් ජාවා ධාවනය කිරීම සඳහා එතීමක් ලෙස ක්‍රියා කරන්නේ නම්, අවසාන පේළිය සෑදීම ගැන සලකා බලන්න. exec java com.myserver.Program "$@"මෙය බාෂ් ජාවා තුළට ක්‍රියාත්මක වීමට හේතු වේ. ඉතින්, ඔබ භාවිතා කරන්නේ එක් අඩු ක්‍රියාවලියක්. එසේම, මව් ක්‍රියාවලිය (ඔබේ ස්ක්‍රිප්ට් ධාවනය කළ) එය පිඩ් එක හරහා නරඹමින් එය 'ජාවා' ක්‍රියාවලියක් වනු ඇතැයි අපේක්ෂා කරන්නේ නම්, ඔබ ක්‍රියාත්මක නොකරන්නේ නම් සමහර අසාමාන්‍ය දේවල් බිඳී යා හැකිය; ක්‍රියාත්මක කිරීම මඟින් ජාවා එකම පයිඩය උරුම කර ගනී.
ග්‍රෙගෝ

7
@dragonxlwang: ඔබගේ ෂෙල් සහාය දක්වන්නේ නම් ඔවුන්ට (උදා: මාලාවක් විචල්ය භාවිතා කළ හැකි bash , zsh , අන් අය, නමුත් සරල Bourne- හෝ POSIX-ෂෙල් නොවේ): සුරකින්න args සමග args=("$@")සහ වෙනම ෂෙල් "වචනය" ලෙස එක් එක් මූලද්රව්යය පුළුල් ( සමාන "$@"සමග) "${args[@]}".
ක්‍රිස් ජොන්සන්

1
භාවිතා කරන විට මතක තබා ගත යුතු "ගොචා" "$@"තිබේද, ඔබ තර්කයක්, හෝ ශුන්‍ය අක්ෂර හෝ වෙනත් විශේෂ අක්ෂර වලින් අවකාශයෙන් ගැලවී ඇත්නම් එය අසාර්ථක වේද?
IQAndreas

98

භාවිතා කරන්න "$@"(සියලුම POSIX අනුකූලතා සඳහා ක්‍රියා කරයි ).

[...], bash හි "$ @" විචල්‍යය දක්වයි, එය අවකාශයන් මගින් වෙන් කරන ලද සියලුම විධාන රේඛා පරාමිතීන් දක්වා විහිදේ.

සිට බෑෂ් උදාහරණයක් විසින් .


7
"$ @" යනු around around වටා උපුටා දැක්වීම් පමණක් නොව, ඇත්ත වශයෙන්ම වෙනස් ආකාරයකින් ගොඩනගා තිබේද?
බෙන්

5
@ben එය තනි විචල්‍යයක් වන නමුත් (කැඩුණු) සිට වෙනස් අගයක් ලබා ගැනීම සඳහා එය වටා ඇති ද්විත්ව උපුටා දැක්වීම් අවශ්‍ය වේ $*. මෙහි historical තිහාසික ප්‍රගතියක් ඇතැයි මම විශ්වාස කරමි. $*සැලසුම් කළ පරිදි ක්‍රියා නොකළ අතර $@එය ප්‍රතිස්ථාපනය කිරීම සඳහා නිර්මාණය කරන ලදී; නමුත් උපුටා දැක්වීමේ නීති ඒවා නම්, ඒ වටා ඇති ද්විත්ව උපුටා දැක්වීම් තවමත් අවශ්‍ය වේ (නැතහොත් එය බිඳුණු $*අර්ථකථන වෙත ආපසු යනු ඇත ).
ත්‍රිත්ව

7
"එසේ නම්" $ @ "හුදෙක් around around වටා උපුටා දැක්වීම් පමණක් නොව, ඇත්ත වශයෙන්ම වෙනස් ආකාරයකින් ගොඩනගා තිබේද?" - සියලු අභිප්‍රායන් සහ අරමුණු සඳහා, ඔව්: stackoverflow.com/a/28099707/162094
ස්ටුවර්ට් බර්ග්

1
ඔබ අඩංගු තිර රචනය කතා නම් echo "$@"ලෙස ./script.sh a "b c" dපසුව ඔබ ලබා a b c dවෙනුවට a "b c" dබොහෝ ලෙසින් වෙනස් වන.
isarandi

7
@isarandi ප්‍රතිදානයේ තවදුරටත් උපුටා දැක්වීම් අඩංගු නොවන බව සත්‍යයක් වුවත්, ඔබ අපේක්ෂා කරන්නේ එයයි ... නමුත් පිටපත තුළ echoතර්ක තුනක් ලැබෙන බවට සහතික වන්න : "a" "b c" "d"(එවිට ෂෙල් එක එහි නූල් ප්‍රසාරණයේ කොටසක් ලෙස එකට එකතු වේ). එහෙත්, ඔබ භාවිතා කරනවා නම්, for i in "$@"; do echo $i; doneඔබ ඇවිත් ඇති කියලා a⏎b c⏎d.
FeRD

68

මට හොඳ පිළිතුරක් ලැබී ඇති බව මට වැටහී ඇති නමුත් මෙන්න "$ @" $ @ "$ *" සහ $ * අතර සංසන්දනයක්

පරීක්ෂණ පිටපතෙහි අන්තර්ගතය:

# cat ./test.sh
#!/usr/bin/env bash
echo "================================="

echo "Quoted DOLLAR-AT"
for ARG in "$@"; do
    echo $ARG
done

echo "================================="

echo "NOT Quoted DOLLAR-AT"
for ARG in $@; do
    echo $ARG
done

echo "================================="

echo "Quoted DOLLAR-STAR"
for ARG in "$*"; do
    echo $ARG
done

echo "================================="

echo "NOT Quoted DOLLAR-STAR"
for ARG in $*; do
    echo $ARG
done

echo "================================="

දැන්, විවිධ තර්ක සමඟ පරීක්ෂණ පිටපත ධාවනය කරන්න:

# ./test.sh  "arg with space one" "arg2" arg3
=================================
Quoted DOLLAR-AT
arg with space one
arg2
arg3
=================================
NOT Quoted DOLLAR-AT
arg
with
space
one
arg2
arg3
=================================
Quoted DOLLAR-STAR
arg with space one arg2 arg3
=================================
NOT Quoted DOLLAR-STAR
arg
with
space
one
arg2
arg3
=================================

35
#!/usr/bin/env bash
while [ "$1" != "" ]; do
  echo "Received: ${1}" && shift;
done;

ඔබේ ස්ක්‍රිප්ටයට ආග්ස් පැමිණෙන්නේ කෙසේදැයි පරීක්ෂා කිරීමට උත්සාහ කරන විට මෙය තව ටිකක් ප්‍රයෝජනවත් වේ යැයි සිතුවා


7
මෙය නියත වශයෙන්ම ඔහුගේ ප්‍රශ්නයට පිළිතුරු දීමට උපකාරී නොවූ නමුත් මෙය ඇත්තෙන්ම ප්‍රයෝජනවත් වේ. ඉහළට!
ඩාරියෝ රුසෝ

2
හිස් පරාමිතියක් සම්මත වූ විට එය කැඩී යයි. ඔබ පරීක්ෂා කර බැලිය යුතුය$#
සෙබී

හොඳ තර්ක පරීක්ෂක, තර්කයක් ලෙස එකඟ වන්න "", ''තර්ක නොමැති නම් එය නිහ is ය. මම මෙය නිවැරදි කිරීමට උත්සාහ කළෙමි, නමුත් එය සඳහා ලූපයක් අවශ්‍ය $#වේ. මම මෙය අවසානයේ එකතු කළෙමි:echo "End of args or received quoted null"
මර්ලින්

9

මෙහි බොහෝ පිළිතුරු නිර්දේශ කරන්නේ $@හෝ $*උපුටා දැක්වීම් සමඟ සහ රහිතව ය, කෙසේ වෙතත් මේවා සැබවින්ම කරන්නේ කුමක්ද සහ ඔබ එසේ කළ යුත්තේ ඇයිද යන්න කිසිවෙකු පැහැදිලි නොකරයි. එබැවින් මෙම පිළිතුරෙන් මෙම විශිෂ්ට සාරාංශය සොරකම් කිරීමට මට ඉඩ දෙන්න :

රූප විස්තරය මෙහි ඇතුළත් කරන්න

උපුටා දැක්වීම් සියල්ලම වෙනස් කරන බවත් ඒවා නොමැතිව දෙදෙනාම සමාන හැසිරීම් ඇති බවත් සැලකිල්ලට ගන්න.

මගේ අරමුණු සඳහා, මට අවශ්‍ය වන්නේ එක් ස්ක්‍රිප්ට් එකක සිට තවත් අක්ෂරයකට පරාමිතීන් යැවිය යුතු අතර ඒ සඳහා හොඳම විකල්පය වන්නේ:

# file: parent.sh
# we have some params passed to parent.sh 
# which we will like to pass on to child.sh as-is

./child.sh $*

උපුටා දැක්වීම් කිසිවක් නොදක්වන $@අතර ඉහත තත්වය තුළද ක්‍රියා කළ යුතුය.


8

මගේ SUN යුනික්ස් හි බොහෝ සීමාවන් ඇත, "$ @" පවා අපේක්ෂිත පරිදි අර්ථ නිරූපණය කර නොමැත. මගේ කාර්යසාධනය $ {@ is වේ. උදාහරණයක් වශයෙන්,

#!/bin/ksh
find ./ -type f | xargs grep "${@}"

මාර්ගය වන විට, මට මෙම විශේෂිත පිටපත තිබිය යුතුව තිබුනේ මගේ යුනික්ස් ද grep -r සඳහා සහය නොදක්වන බැවිනි


1
මෙය බාෂ් ප්‍රශ්නයකි; ඔබ භාවිතා කරන්නේksh
ත්‍රිත්ව

6

ඔබ $@වෙනත් අක්ෂර සමඟ උපුටා ගත් නූලකට ඇතුළත් කරන්නේ නම් , බහු තර්ක ඇති විට හැසිරීම ඉතා අමුතු ය, උපුටා දැක්වීම් තුළ පළමු තර්කය පමණක් ඇතුළත් වේ.

උදාහරණයක්:

#!/bin/bash
set -x
bash -c "true foo $@"

අස්වැන්න:

$ bash test.sh bar baz
+ bash -c 'true foo bar' baz

නමුත් පළමුව වෙනස් විචල්‍යයකට පැවරීම:

#!/bin/bash
set -x
args="$@"
bash -c "true foo $args"

අස්වැන්න:

$ bash test.sh bar baz
+ args='bar baz'
+ bash -c 'true foo bar baz'

3
එය විසන්ධි කිරීම මම ප්‍රතික්ෂේප නොකරමි, නමුත් එය සැබවින්ම අර්ථවත් වන්නේ බාෂ්හි අර්ථ නිරූපණය "$@"තුළ ය. $@සහ අතර ඇති ප්‍රධාන වෙනස $*සහ ඒවා දෙකම ප්‍රයෝජනවත් වන්නේ ඇයිද යන්න පැහැදිලි කිරීමටද එය උපකාරී වේ. සිට bash(1)man පිටුව විශේෂ සිටුවම්: " *- පුළුල්, උද්ධෘත පාඨ තුළ සිදුවන විට, එය එක් එක් පරාමිතිය වටිනාකම සහිත තනි වචනය පුළුල් [...] එනම්, "$*"සමාන වේ "$1c$2c..."කොහේද, cවේ [ $IFS]." ඇත්ත වශයෙන්ම, ඔබේ පළමු උදාහරණය $*වෙනුවට භාවිතා $@කිරීම දෙවන අනුවාදයට සමාන ප්‍රතිදානයක් ලබා ගනී.
FeRD

2
දැන්, එය සසඳා බලන්න "$@". නැවතත් මෑන් පිටුවෙන්: " @- ද්විත්ව උපුටා දැක්වීම් තුළ ප්‍රසාරණය සිදු වූ විට, සෑම පරාමිතියක්ම වෙනම වචනයකට විහිදේ. එනම්, "$@"සමාන වේ "$1" "$2"… ද්විත්ව උපුටා දැක්වීමේ ව්‍යාප්තිය වචනයක් තුළ සිදුවුවහොත්, පළමු පරාමිතියේ ප්‍රසාරණය සම්බන්ධ වේ මුල් වචනයේ ආරම්භක කොටස සමඟ, අවසාන පරාමිතියේ ප්‍රසාරණය මුල් වචනයේ අවසාන කොටස සමඟ සම්බන්ධ වේ. ... ඇත්ත වශයෙන්ම, ඔබේ කේතය තිබුනේ නම් bash -c "true foo $@ bar baz", එය test.sh one twoශුද්ධ ලෙස ක්‍රියාත්මක කරන්න bash -c 'true foo one' 'two bar baz'.
FeRD

1
ලියකියවිලි උපුටා දැක්වීම් හා තොරතුරු වලට ස්තූතියි $*, එය පවතින බව මට අමතක බව පෙනේ ..
කොලින් එම්

හෙහ්. මම ප්‍රතිවිරුද්ධ දෙයයි, $@මම මුලින්ම ෂෙල් ස්ක්‍රිප්ටින් කිරීම ආරම්භ කරන විට කම්පනය ලබා ගනිමින් සිටියෙමි, එය තවමත් එහි ඇති බව මට මතක් කර දිය යුතුය. "$*"ස්ක්‍රිප්ට් වල භාවිතා කිරීම සාමාන්‍ය දෙයක් විය ... එවිට කතුවරයා එය ඔවුන්ගේ තර්ක සියල්ලම එකට බිඳ දමනු ඇති බව වටහා ගනු ඇත, එබැවින් ඔවුන් වචන බෙදීම් සමඟ සියලු ආකාරයේ සංකීර්ණ විකාරයන් උත්සාහ කරනු ඇත "$*", නැතහොත් ලූප මගින් ආග් ලැයිස්තුවක් එක්රැස් කරයි. කට shiftපමණක් භාවිතා එකින් එක බිඳ ඔවුන් බේරා ගැනීමට ... $@එය විසඳිය නොහැකි. ( ${var[*]}${var[@]}
අරෂ්

මෙහි ඇති සැබෑ ගැටළුව නම් ඔබ භාවිතා bash -cකරන්නේ කිසිම තේරුමක් නැති ආකාරයටය.
ත්‍රිත්ව

4

සමහර විට ඔබට ඔබගේ සියලු තර්ක සම්මත කිරීමට අවශ්‍ය නමුත් ඊට පෙර ධජයක් (උදා --flag)

$ bar --flag "$1" --flag "$2" --flag "$3"

ඔබට මෙය පහත ආකාරයෙන් කළ හැකිය:

$ bar $(printf -- ' --flag "%s"' "$@")

සටහන: අමතර ක්ෂේත්රයේ පැලෙන වළක්වා ගැනීමට, ඔබ කථාකරන %sහා $@, හා තනි string සහිත වළක්වා ගැනීමට, ඔබ යන උප කබොළ උපුටා නොහැකි printf.


3

ඔබට අවකාශයක් හෝ පැන ගිය අක්ෂර තිබේ නම් හැර, හොඳින් ක්‍රියා කරයි. මෙම නඩුවේ තර්ක ග්‍රහණය කර පිටපතෙහි ඇතුළත කෙටි පණිවිඩයක් යැවීමට මට ක්‍රමයක් සොයාගත නොහැක.

මෙය ප්‍රයෝජනවත් විය හැකි නමුත් එය කැතයි

_command_opts=$( echo "$@" | awk -F\- 'BEGIN { OFS=" -" } { for (i=2;i<=NF;i++) { gsub(/^[a-z] /,"&@",$i) ; gsub(/ $/,"",$i );gsub (/$/,"@",$i) }; print $0 }' | tr '@' \' )

2

bar "$@" සමාන වේ bar "$1" "$2" "$3" "$4"

උද්ධෘත ලකුණු වැදගත් බව සැලකිල්ලට ගන්න!

"$@", $@, "$*"හෝ $*තරමක් වෙනස් එක් එක් වටේ සංචාරවල යෙදෙමින් මෙම විස්තර කර ඇති පරිදි මිදීමේ හා අකාර සම්බන්ධයෙන් කරනු stackoverflow පිළිතුර .

සමීපව සම්බන්ධ වූ එක් භාවිත අවස්ථාවක් නම්, දී ඇති සියලු තර්ක මේ ආකාරයේ තර්කයක් තුළ සම්මත කිරීමයි :

bash -c "bar \"$1\" \"$2\" \"$3\" \"$4\"".

මෙය සාක්ෂාත් කර ගැනීම සඳහා මම @ kvantour ගේ පිළිතුරේ විචල්‍යතාවයක් භාවිතා කරමි:

bash -c "bar $(printf -- '"%s" ' "$@")"


1

"${array[@]}"ඕනෑම අරාවක් කඩාවැටීම සඳහා නිවැරදි ක්‍රමයයි. මට සම්පූර්ණ වංචා පත්‍රිකාවක් සැපයීමට අවශ්‍යයි: තර්ක පිළියෙළ කරන්නේ කෙසේද, ඒවා මඟ හැරීම සහ සැකසීම.

pre.sh-> foo.sh-> bar.sh.

#!/bin/bash

args=("--a=b c" "--e=f g")
args+=("--q=w e" "--a=s \"'d'\"")

./foo.sh "${args[@]}"
#!/bin/bash

./bar.sh "$@"
#!/bin/bash

echo $1
echo $2
echo $3
echo $4

ප්‍රති result ලය:

--a=b c
--e=f g
--q=w e
--a=s "'d'"
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.