ใช้การอ้างอิงตัวแปร“ ภายใน” ตัวแปรอื่น


27

ฉันแน่ใจว่ามันค่อนข้างง่ายฉันไม่ทราบวิธีการทำ

#!/usr/bin/ksh
set `iostat`
myvar=6

ฉันต้องการบางสิ่งecho ${$myvar}ที่ฉันต้องการตีความว่า${$myvar}-> ${6}->value


4
ระยะทางเทคนิคคือตรงตัวแปร
Thor

คำตอบ:


29

คุณสามารถทำสิ่งนี้ได้evalในตัวกับเชลล์ที่ดีหลายตัวรวมถึง ksh:

#!/usr/bin/ksh
set $(iostat)
myvar=6
eval "echo \${$myvar}"

เคล็ดลับคือการอ้างอิงสตริงที่คุณป้อนเป็นสองเท่าเพื่อevalให้ $ myvar ได้รับการแทนที่ด้วย "6" และเพื่อแบ็กสแลชเครื่องหมายดอลลาร์ภายนอกเพื่อให้evalรับสตริง "$ 6"

ฉันได้รับ "ผู้ใช้%" สำหรับผลลัพธ์ แต่ฉันลองใช้กับเครื่อง RHEL แบบหลายโปรเซสเซอร์


3
คุณเป็นประมุขสูงสุดอย่างเป็นทางการของสัปดาห์ b / c ที่ยังทำงานใน ksh อันยิ่งใหญ่อย่างเหลือเชื่อ (pdksh จริงๆ) ใน OpenBSD 5.4 หากคุณต้องการ var ชุดVVมูลค่าของ var ที่มีชื่ออยู่ใน var ที่VNvv=$( eval "echo \$$vn" )เพียงแค่ทำ ขอบคุณตัน!
execNext

25

การอ้างอิงตัวแปรทางอ้อม

เชลล์ขั้นสูงที่ทันสมัยมีวิธีการอ้างอิงค่าของตัวแปรที่มีชื่อถูกเก็บไว้ในตัวแปรอื่น น่าเสียดายที่วิธีการนั้นแตกต่างกันระหว่าง ksh, bash และ zsh

ใน mksh ≥R39bคุณสามารถสร้างmyvarnameref:

typeset -n myvar=6
echo "$myvar"

สิ่งนี้ไม่ทำงานใน ATT ksh93 เพราะมันไม่รองรับ namerefs กับพารามิเตอร์ตำแหน่ง ในกรณีที่คุณมีตัวแปรที่มีชื่อตัวแปรคุณสามารถใช้วิธีนี้

foo=bar
typeset -n myvar=foo
echo "$myvar"  # prints bar

ใน bash ≥2.0คุณสามารถเขียนได้

echo "${!myvar}"

ใน zsh คุณสามารถเขียนได้

echo ${(P)myvar}

ในเปลือกหอยเก่ารวมทั้ง ksh88 และ pdksh, ไล่เบี้ยเท่านั้นคุณเมื่อคุณมีตัวแปรที่มีชื่อตัวแปรอื่นและต้องการที่จะใช้ค่าของตัวแปรนี้eval, ตามที่อธิบายไว้โดยบรูซเอดิเกอร์ วิธีนี้ใช้ได้กับเชลล์ Bourne / POSIX ทุกรุ่น

eval "value=\${$myvar}"
echo "$value"

การใช้อาเรย์

นี่เป็นวิธีที่ดีที่สุดที่นี่: ง่ายและพกพาได้มากกว่า

สำหรับกรณีการใช้งานของคุณในเชลล์ที่มีอาร์เรย์ (ตัวแปร ksh ทั้งหมด, bash ≥2.0, zsh) คุณสามารถกำหนดให้กับตัวแปรอาร์เรย์และใช้องค์ประกอบที่คุณต้องการ ระวังว่า ksh และทุบตีอาร์เรย์เริ่มต้นเลขที่ 0 แต่จะเริ่มต้นวันที่ 1 zsh จนกว่าคุณจะออกหรือsetopt ksh_arraysemulate ksh

set -A iostat -- $(iostat)
echo "${iostat[5]}"

หากคุณต้องการคัดลอกพารามิเตอร์ตำแหน่งไปยังตัวแปรอาร์เรย์a:

set -A a -- "$@"

ใน ksh93, mksh ≥R39b, bash ≥2.0และ zsh คุณสามารถใช้ไวยากรณ์การกำหนดอาเรย์:

iostat=($(iostat))
echo "${iostat[5]}"

ว้าวโซลูชัน 'Bourne / POSIX' ของคุณยังทำงานใน ksh / pdksh ของ OpenBSD 5.4 eval "vv=\${$vn}"ที่จะนำไปใช้กับตัวอย่างในความคิดเห็นของฉันที่จะตอบบรูซเอดิเกอร์เหนือเพียงแค่ทำ Merci beaucoup ท่านใจดี
execNext

1

ตามที่ระบุโดย Gilles (ซึ่งเป็นbashส่วนหนึ่งของคำตอบ) ก็ไม่ทำให้การใช้งานของ Bruce Ediger เป็นโมฆะ (ต่อไปนี้เป็นวิธีการทำแบบพกพาeval) นี่เป็นวิธีทำnamerefในช่วงไม่นานมานี้mksh(และ AT&T ksh93 ยกเว้น - @ @ Gilles ไม่สามารถอ้างถึงพารามิเตอร์ตำแหน่งใน AT&T ksh เฉพาะกับพารามิเตอร์ที่มีชื่อ):

#!/bin/mksh
set -- $(iostat)
nameref myvar=6
echo $myvar

เพิ่ม--หลังsetสำหรับความต้านทานที่ดีขึ้นอีกด้วย


ในฐานะของ ksh 93u, namerefs ไม่สามารถอ้างอิงพารามิเตอร์ตำแหน่ง ( typeset: 6: invalid variable name)
Gilles 'หยุดชั่วร้าย'

0

การใช้งานของอาร์เรย์อื่น

ยังไม่ได้ใช้ ksh หรือตัวแปรใด ๆ เป็นระยะเวลาหนึ่งดังนั้นฉันไม่แน่ใจว่า ksh (หรือ bash) มีความสามารถคล้ายกันหรือไม่ เปลือกหลักของฉันคือ zsh ฉันใช้อาร์เรย์เมื่อจัดการเอาต์พุตจากคำสั่งเช่นiostatเพราะมันสร้างหลายบรรทัดและไม่ใช่ทุกบรรทัดที่มีรูปแบบ / ความยาวเหมือนกัน

#! /bin/zsh
IOStatOutput=("${(@f)$(iostat)}") # Produces one element per line

ข้างต้นยังข้ามการใช้พารามิเตอร์ตำแหน่ง ตอนนี้ถ้าคุณต้องการที่จะสร้างพูดอาร์เรย์ของอุปกรณ์:

for Element in {7..${#IOStatOutput}} # Devices listed in elements 7 thru the last
do
    DevList+=( ${${=IOStatOutput[Element]}[1]} )
done

ฉันพบว่าชิ้นเล็ก ๆ จัดการง่ายกว่ามาก คุณอาจหรืออาจไม่จำเป็นต้องใช้การอ้างอิงตัวแปรทางอ้อมขึ้นอยู่กับรหัสของคุณ รู้วิธีการทำงานยังคงเป็นสิ่งที่ดีที่จะรู้ ฉันใช้มันเอง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.