การกำหนดรหัสทางออกให้กับตัวแปรโลคัลเชลล์


คำตอบ:


59

local t1=$(exit 1) บอกเชลล์ให้กับ:

  • ทำงานexit 1ใน subshell;
  • เก็บเอาท์พุทของมัน (เช่นในข้อความที่ส่งออกไปยังเอาต์พุตมาตรฐาน) ในตัวแปรt1ท้องถิ่นเพื่อฟังก์ชั่น

มันเป็นเรื่องปกติที่t1กลายเป็นว่าว่างเปล่า

( $()เรียกว่าการทดแทนคำสั่ง )

รหัสทางออกจะถูกกำหนดไว้เสมอเพื่อ$?ให้คุณสามารถทำได้

function0()
{
  (exit 1)
  echo "$?"
}

เพื่อให้ได้เอฟเฟกต์ที่คุณต้องการ แน่นอนคุณสามารถกำหนด$?ให้กับตัวแปรอื่น:

function0()
{
  (exit 1)
  local t1=$?
  echo "$t1"
}

1
คุณก็รู้ว่าคุณสามารถใส่ผลตอบแทนเข้าไปในท่อได้เช่นกัน `$ (trap 'printf" :: ERRNO: $? "' 0; # ตอนนี้ทำทุกอย่างอย่างไรก็ตาม - กับดักนั้นจะทำให้แน่ใจว่าสตริงสุดท้ายที่เขียนคือการส่งคืนสุดท้ายสำหรับบริบทการทดแทนทั้งหมด
mikeserv

1
@mikeserv คุณพลาด backtick ไหม? $(trap 'printf "::ERRNO:$?"' 0; # now do whatever however
Doktor J

13

รหัสออกถูกเก็บเป็น$? ตัวแปร. การใช้การแทนที่คำสั่งจะจับเฉพาะเอาต์พุตคุณควรใช้(... ) เพื่อสร้างเชลล์ย่อย :

#!/bin/bash

func() {
  (exit 1)
  local t1=$?
  printf '%d\n' "$t1"
}

func

ประเด็นของการมอบหมายt1=$?คือการใช้มันไม่ใช่? และจะไม่$?ได้รับการอุดตันโดย op ที่ได้รับมอบหมาย? ฉันเดาว่าฉันถามว่ามันไม่ควรจะเป็นprintf '%d\n' "${t1}"
Dani_l

@Dani_l: ขอบคุณนั่นเป็นตัวพิมพ์ผิด Updated
cuonglm

โปรดทราบว่าการแทนที่คำสั่งจะจับภาพมาตรฐานเท่านั้นยกเว้นว่ามีการเปลี่ยนเส้นทางที่แตกต่างกัน
phyatt

7

ในbashงานนี้:

loc(){  local   "x=$(exit "$1"):$?"
        printf  '$%s:\t%d\n' \
                 x "${x##*:}" \? "$?"
}

มันเกี่ยวข้องกับลำดับของการประเมินคำสั่งและการกำหนดตัวแปร localมีค่าส่งคืนทั้งหมดเป็นของตัวเอง - และเป็นคำสั่งในการดำเนินการในปัจจุบันไม่ใช่การทดแทนคำสั่ง เหตุผลที่ชอบ ...

x=$(exit 1); echo "$?"

... สามารถคืนค่า 1 ได้เนื่องจากไม่มีการส่งคืนในคำสั่งนั้นยกเว้นการเรียกใช้ subshell เพื่อกำหนด$xค่าของ - ดังนั้นจึง$?ไม่ได้รับการอุดตันเหมือนในกรณีจริง ๆ ทุกกรณีที่ใช้การแทนที่คำสั่ง

อย่างไรก็ตามกับlocalมันไม่ได้รับ clobbered - แต่ถ้าคุณจับมันที่เพียงเวลาที่เหมาะสม - ซึ่งเป็นขณะที่การขยายตัวยังคงถูกประเมินและก่อนที่จะ local 's กิจวัตรมีโอกาสที่จะบังคับมัน - คุณยังสามารถกำหนด

unset x; loc 130; echo "${x-\$x is unset}"

พิมพ์ ... ...

$x: 130
$?: 0
$x is unset

คุณควรรู้ว่าในหลาย ๆ เชลล์คุณไม่สามารถพึ่งพา$?การตั้งค่าการประเมินกลางด้วยวิธีนี้ ในความเป็นจริงที่ว่าอาจจะเป็นเพราะเปลือกหอยเหล่านั้นไม่ได้รบกวนการประเมินอีกครั้งในทุกจุดเชื่อมต่อที่เป็นไปได้อาจจะbashไม่ - ซึ่งผมจะเถียงเป็นพฤติกรรมที่อาจจะดีกว่าbash's คุณต้องการให้ล่ามวนวนซ้ำวนซ้ำซึ่งมีแนวโน้มที่จะถูกเขียนทับก่อนที่คุณจะมีโอกาสได้ใช้จริงหรือไม่?

อย่างไรก็ตามนั่นคือวิธีที่คุณสามารถทำได้


-1

ขึ้นอยู่กับสาเหตุที่คุณพยายามรับรหัสทางออกที่คุณสามารถเรียกใช้if some-command; then echo "Success $?"; else echo "Failure $?"; fiซึ่งไม่ได้ทำอะไรกับผลลัพธ์ของคำสั่ง แต่จะประเมินรหัสทางออกของการเรียกใช้คำสั่ง คุณสามารถเพิ่มor( or$ ( around the command and you'll still get the same results. A better example might beถ้า grep -q 'somestring' somefile; echo "พบรหัสทางออก somestring เป็น $?"; อื่น "ไม่พบรหัสทางออก somestring เป็น $?"; fi`

คุณสามารถทดสอบโค้ดส่งคืนของฟังก์ชันซึ่งอาจเป็นreturn 3โค้ดส่งคืนอย่างชัดเจนหรือโดยนัยซึ่งเป็นผลมาจากคำสั่งสุดท้ายในกรณีนี้คุณต้องระวังว่าคุณไม่มีแอนechoที่ส่วนท้ายของ ฟังก์ชั่นมิฉะนั้นจะมาสก์ / รีเซ็ตรหัสทางออกก่อนหน้า

command_last () {
  echo "True is `true`"
  echo "False is `false`"
  false
}
command_last; echo $?
# Outputs:
# True is 0
# False is 1
# 1

echo_last () {
  echo "True is `true`"
  echo "False is `false`"
  false
  # echo'ing literally anything (or nothing) returns true aka exit 0
  echo
}
echo_last; echo $?
# Outputs:
# True is 0
# False is 1
#            # Blank line due to empty echo
# 0

ในที่สุดก็เป็นเคล็ดลับที่สกปรกเนื่องจากคุณไม่สามารถทำVAR=(SOME_COMMAND)เพราะเป็นคำนิยามอาร์เรย์ดังนั้นคุณจำเป็นต้องVAR=()VAR=( $(echo 'Some value') )


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