Gán mã thoát cho một biến cục bộ shell


Câu trả lời:


58

local t1=$(exit 1) nói với cái vỏ để:

  • chạy exit 1trong một subshell;
  • lưu trữ đầu ra của nó (như trong, văn bản mà nó xuất ra đầu ra tiêu chuẩn) trong một biến t1, cục bộ cho hàm.

Do đó, bình thường mà t1kết thúc là trống rỗng.

( $()được gọi là thay thế lệnh .)

Mã thoát luôn được gán cho $?, vì vậy bạn có thể làm

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

để có được hiệu quả mà bạn đang tìm kiếm. Tất nhiên bạn có thể gán $?cho một biến khác:

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

1
Bạn biết đấy, bạn luôn có thể đặt trở lại vào đường ống, quá. `$ (bẫy 'printf" :: ERRNO: $? "' 0; # bây giờ làm bất cứ điều gì - cái bẫy đó sẽ đảm bảo chuỗi cuối cùng được viết là sự trở lại cuối cùng cho toàn bộ bối cảnh thay thế.
mikeerv

1
@mikeerv bạn có bỏ lỡ backtick không? $(trap 'printf "::ERRNO:$?"' 0; # now do whatever however
Doktor J

12

Mã thoát được lưu trữ trong $? Biến đổi. Sử dụng thay thế lệnh chỉ thu được đầu ra, bạn nên sử dụng (...) để tạo lớp con :

#!/bin/bash

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

func

điểm của bài tập t1=$?là sử dụng nó, không? và sẽ không $?bị tắc nghẽn bởi nhiệm vụ op? Tôi đoán tôi đang hỏi liệu có nên khôngprintf '%d\n' "${t1}"
Dani_l

@Dani_l: Cảm ơn, đó là một lỗi đánh máy. Đã cập nhật.
cuonglm

Lưu ý rằng Thay thế lệnh chỉ nắm bắt tiêu chuẩn trừ khi được chuyển hướng khác nhau.
phyatt 17/03/2017

7

Trong bashtác phẩm này:

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

Nó phải làm theo thứ tự đánh giá lệnh và gán biến. localcó giá trị trả về của riêng nó - và đó là lệnh hiện đang thực thi, không phải là lệnh thay thế. Lý do như ...

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

... có thể trả về 1 là vì không bao giờ có lệnh trả về ngoại trừ lệnh chạy con để gán $xgiá trị - vì vậy $?thực tế không bị ghi đè như trong thực tế mọi trường hợp khác sử dụng thay thế lệnh.

Dù sao, với localcũng bị tắc nghẽn - nhưng nếu bạn bắt được nó vào đúng thời điểm - đó là trong khi các bản mở rộng vẫn đang được đánh giá và trước khi local các thói quen có thể bị chặn lại - bạn vẫn có thể gán nó.

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

... bản in ...

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

Mặc dù vậy, bạn nên biết rằng trong nhiều hệ vỏ, bạn không thể dựa vào $?việc đánh giá giữa theo cách đó. Trên thực tế, đó có lẽ là do những cái vỏ đó không bận tâm đến việc đánh giá lại ở mọi thời điểm có thể xảy ra như có lẽ bash- điều mà tôi cho rằng có lẽ là hành vi tốt hơn so với bash. Bạn có thực sự muốn trình thông dịch của bạn đánh giá đệ quy các giá trị vòng lặp rất có khả năng bị ghi đè trước khi bạn có cơ hội sử dụng chúng không?

Dù sao, đó là cách bạn có thể làm điều đó.


-1

Tùy thuộc vào lý do tại sao bạn đang cố lấy mã thoát, bạn cũng có thể chạy if some-command; then echo "Success $?"; else echo "Failure $?"; fimà không làm gì với đầu ra của lệnh, nó chỉ đánh giá mã thoát của lệnh chạy. Bạn có thể thêm or( or$ ( around the command and you'll still get the same results. A better example might benếu grep -q 'somestring' somefile; sau đó lặp lại "Đã tìm thấy mã thoát nội địa là $?"; Khác "Không tìm thấy mã thoát nội địa là $?"; Fi`.

Bạn cũng có thể kiểm tra mã trả về của hàm có thể là return 3mã trả về rõ ràng hoặc mã ngụ ý là kết quả của lệnh cuối cùng, trong trường hợp này bạn cần cẩn thận rằng bạn không có mã echoở cuối chức năng, nếu không nó che / đặt lại mã thoát trước đó.

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

Cuối cùng là một mánh khóe bẩn vì bạn không thể làm được VAR=(SOME_COMMAND)vì đó VAR=()là một định nghĩa mảng nên bạn cần phải làm VAR=( $(echo 'Some value') ).


Tất cả các kết quả đầu ra được tuyên bố là sai, do thực tế là việc thay thế lệnh không cung cấp mã thoát, đó là toàn bộ điểm của câu hỏi. Không rõ "mánh khóe bẩn" này có liên quan gì.
Nick Matteo
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.