Logs

子shell如何在變數(而不是文件)中返回數據並同時輸出不同的日誌?

  • June 23, 2021

假設我有以下 javascript:

   const something = doSomething();
   
   function doSomething() {
       console.log("About to do something");
       
       const a = doSomethingElse();
       if (a == "dog") {
           console.log("Worked");
           console.log("Now let's do xyz");
           return "cat";
       } else {
           console.log("failed for some reason");
           return "horse";
       }
   }
   
   function doSomethingElse() {
       console.log("About to do more");
       console.log("Done doing more stuff");
       
       return "dog";
   }

我們如何在 bash 中實現這一點?我想實時查看日誌,而不是將它們儲存在文件中以備後用?我正在考慮類似以下的內容,但隨後所有內容都混合在一起,再加上 bash 中的 return 關鍵字用於其他目的並且不能接受字元串。

   something=$(doSomething);
   
   function doSomething() {
       console_log "About to do something";
       
       a=$(doSomethingElse);
       if [[$a = "dog"]]; then
           console_log "Worked";
           console_log "Now let's do xyz";
           echo "cat"; # Wish I could do return "cat" ...
       else
           console_log "failed for some reason";
           echo "horse"; # Wish I could do return "horse" ...
       fi;
   }
   
   function doSomethingElse() {
       console_log "About to do more";
       console_log "Done doing more stuff";
       
       echo 'dog'; #Wish I could do return "dog" ...
   }
   
   function console_log() {
       #Is echo the right thing, or tee, or something else ?
       echo $1;
   }

是不是有多個輸出流來實現這一點?或者,是否有替代 $() 來分配變數?我試過玩 tee, &*, &? 和 3>1 的東西,我無法理解這一切…… :(

我在 CentOS 7.9 下有 bash 4.2.46

感謝您的幫助 :)

這應該沒問題:

#! /bin/bash -

doSomething() {
   print_err "About to do something"

   a="$(doSomethingElse)"
   if [[ "$a" = "dog" ]]; then
       print_err "Worked"
       print_err "Now let's do xyz"
       printf '%s' "cat"
   else
       print_err "failed for some reason"
       printf '%s' "horse"
   fi
}

doSomethingElse() {
   print_err "About to do more";
   print_err "Done doing more stuff";
   printf '%s' 'dog'
}

print_err() {
   # Print to stderr as we do this in functions
   # that print result to stdout
   printf '%s\n' "$1" >&2
}

something="$(doSomething)"
# Making it readonly would be somewhat similar to const
readonly something

printf '%s\n' "$something"

需要:

  • something="$(doSomething)"聲明後移動doSomething。Bash 在讀取的基礎上執行語句。(為什麼你也可以exit用來中止腳本。)在 JavaScript 中,程式碼被讀取、編譯和執行。
  • 在您if test的括號和參數之間需要空格。
    一般來說: [Bash 運算符 [[ vs vs ( vs ((?
  • 您必須將非數據重定向到stderron echo,>&2否則所有輸出都分配給變數,例如a.

2>&-、2>/dev/null、|&、&>/dev/null和>/dev/null的區別 2>&1

shell的控制和重定向操作符是什麼?

一般來說:

除此之外,替換[[[將使其sh合規。“sh 兼容”是什麼意思?

還要查看變數的範圍。有沒有辦法讓本地命令可移植地執行以破折號 ksh bash 和 zsh?

如,您可以完成:

set_something() {
   something='cat'
}

set_something
printf 'something="%s"\n' "$something"

JavaScript 不適用於流,shell 可以。簡化它:

  • readfrom stdin,文件描述符0(標準輸入)
  • writeto stdout,文件描述符1(標準輸出)
  • writeto stderr,文件描述符2(標準錯誤)

除此之外,還可以打開新的、讀/寫文件等。

/dev/stdin、/dev/stdout 和 /dev/stderr的可移植性如何?


返回值。

Bash 函式不會“返回”字元串。當一個人這樣做:

foo="$(some command)"

一個分配到的標準some command輸出foo。如果不更改程式碼中非數據列印的重定向,您可以通過以下方式查看:

# In doSomething():
   printf 'a="%s"\n' "$a" >&2

# At end:
printf '"%s"\n' "$something"

你會得到:

a="About to do more
Done doing more stuff
dog"
something="About to do something
failed for some reason
horse"

如您所見,分配了整個輸出。

在*“修復”之後,可以通過將 stderr 重定向到 stdout來*擷取兩者:stdout``stderr

foo="$(some command 2>&1)"

退出程式碼

然而,Shell 函式確實有退出程式碼,就像任何程序一樣。如果沒有顯式返回值,則它是在該函式中執行的最後一個命令的退出狀態。0沒問題,其他任何東西都被認為是測試中的錯誤。

簡單的例子:

#! /bin/bash -

foo() {
   printf 'I am foo\n'
   return 1
}
greetings() {
   if [ "$1" = "hi" ]; then
       printf 'Hello\n'
   else
       printf 'I do not know what to do with %s\n' "$1"
       return 12
   fi
}
if foo; then
   printf 'OK\n'
else
   printf 'FAIL\n'
fi

printf '\n## Try greetings "yo":\n'
greetings yo
ecode=$?
printf 'greetings() returned %d\n' "$ecode"

printf '\n## Try greetings "hi":\n'
greetings hi
ecode=$?
printf 'greetings() returned %d\n' "$ecode"

結果:

I am foo
FAIL

## Try greetings "yo":
I do not know what to do with yo
greetings() returned 12

## Try greetings "hi":
Hello
greetings() returned 0

一些幫助shellcheck

不是萬無一失的,但對 linting 腳本有很大幫助。

您可以將其用作命令行工具、線上粘貼程式碼或將其合併到您的編輯器中。

例如,如果您將 Vim 與 ALE 一起使用,它會shellcheck在安裝後繼續執行。請注意,儘管與發行版捆綁在一起的軟體包可能有些過時。例如,Ubuntu 18.04 使用 v0.4.6

https://github.com/koalaman/shellcheck

一般的 Shell 腳本

bash和等人一起玩。可以對學習有用。總是考慮你想做什麼。例如,文本處理幾乎總是使用其他工具更好地完成。然後可以使用 shell 腳本將它們粘合在一起。使用管道等 - unices 的一部分力量。例如sortjoin, cut, tr, paste, uniq, find, grep, cat, date, tail, head, xargs, wc, fold, column, paste, 等等。

互動式 shell 腳本不僅可以使用它,還可以使用各種功能擴展您的 shell。

對於更高級的數據類型和復雜性,可以使用perl,python以及其他範圍廣泛的內容,甚至c. c一般來說,這是一種在較低級別了解系統的非常好的方法。

awksed對於處理awk更容易學習的文本也非常強大和有用。

引用自:https://unix.stackexchange.com/questions/655362