簡體   English   中英

將while循環的輸出發送到bash函數

[英]Sending the output of a while loop to a bash function

我創建了一個.bashrc文件,其中有兩個功能。 一個在while循環中循環遍歷文件的每一行。 我試圖保存行的內容(如果它們符合特定條件),然后將所有三個匹配項傳遞給第二個函數,然后將它們回顯。 但是,我嘗試了導出變量,還嘗試了管道傳遞給第二個函數,但均無效。 當我嘗試在代碼示例中進行說明時,管道的行為也很奇怪。

readAndPipe() {
  while read -r line || [[ -n "$line" ]]; do
  (   
  if [[ $line == FIRSTNAME=BOB ]]; then
     echo $line;
  fi; 
  if [[ $line == LASTNAME=SMITH ]]; then
     echo $line;
  fi; 
  if [[ $line == BIRTHMONTH=AUGUST ]]; then
     echo $line;
  fi; 
  ); done < "file.txt" | printArguments $1 #pass the original command line argument;
}

printArguments() {
    #This is where the weirdness happens
    echo $@                   #Prints: only the original command line argument
    echo $#                   #Prints: 1
    echo $2 $3 $4             #Prints nothing
    varName=$(cat $2 $3 $4)
    echo $varName             #Prints: FIRSTNAME=BOB
                              #        LASTNAME=SMITH
                              #        BIRTHMONTH=AUGUST
    cat $2 $3 $4              #Prints nothing
    echo $(cat $2 $3 $4)      #Prints nothing
    cat $2 $3 $4 | tr "\n" '' #Prints tr: empty string2
}

顯然我不是bash專家,所以我確定這里有很多錯誤,但是我想知道的是

  1. 這些看似神奇的$ 2 $ 3 $ 4參數是什么,這些參數不是通過echo打印的,而只可以被cat使用一次。
  2. 在while循環中保存內容並將其傳遞給另一個函數以便我可以回顯的正確方法是什么?

$@$*$1$2等是傳遞給函數的參數 例如,在myfunc foo bar baz ,我們有$ 1 == foo,$ 2 == bar和$ 3 == baz。

將數據通過管道傳輸到函數時,必須從stdin中檢索數據:

myfunc() {
    data=$(cat)
    echo "I received: >$data<"
}
for n in {1..5}; do echo "x=$n"; done | myfunc

產生

I received: >x=1
x=2
x=3
x=4
x=5<

varName=$(cat $2 $3 $4)之所以有效,是因為$ 2 $ 3和$ 4 為空 ,所以外殼程序會看到:
varName=$(cat )

cat“只能工作一次”的原因是因為您正在消費流。 一旦消耗掉,它就消失了。 “你不能吃蛋糕也不能吃。”


printArguments函數可以使用readarray命令將傳入的行捕獲到數組中,而不是使用cat來將所有傳入的文本捕獲到變量中:

printArguments() {
    readarray -t lines
    echo "I have ${#lines[@]} lines"
    echo "they are:"
    printf ">>%s\n" "${lines[@]}"
}
{ echo foo; echo bar; echo baz; } | printArguments

輸出

I have 3 lines
they are:
>>foo
>>bar
>>baz

在交互式bash提示符下鍵入help readarray了解更多信息。

想象一個腳本:

 func() {
       echo $#  # will print 2, func were executed with 2 arguments
       echo "$@"  # will print `arg1 arg2`, ie. the function arguments
       in=$(cat)   # will pass stdin to `cat` function and save cat's stdout into a variable
       echo "$in" # will print `1 2 3`
 }
 echo 1 2 3 | func arg1 arg2
 #                  ^^^^^^ function `func` arguments
 #          ^ passed one command stdout to other command stdin
 # ^^^ outputs `1 2 3` on process stdout
  1. 不帶任何參數的cat調用,讀取stdin並將其輸出到stdout
  2. 在命令替換中調用命令會傳遞標准輸入(即in=$(cat)將讀取標准輸入,因為普通的cat只會將輸出(即cat的標准輸出)保存到變量中)

對您的腳本:

readAndPipe() {
  # the while read line does not matter, but it outputs something on stdout
  while read -r line || [[ -n "$line" ]]; do
         echo print something 
  # the content of `file.txt` is passed as while read input
  done < "file.txt" | printArguments $1 # the `print something` (the while loop stdout output) is passed as stdin to the printArguments function
}

printArguments() {
    # here $# is equal to 1
    # $1 is equal to passed $1 (unless expanded, will get to that)
    # $2 $3 $4 expand to nothing
    varName=$(cat $2 $3 $4) # this executes varName=$(cat) as $2 $3 $4 expand to nothing
    # now after this point stdin has been read (it can be read once, it's a stream or pipe
    # is you execute `cat` again it will block (waiting for more input) or fail (will receive EOF - end of file)
    echo $varName             #Prints: `print something` as it was passed on stdin to this function
}

如果文件file.txt僅包含:

FIRSTNAME=BOB
LASTNAME=SMITH
BIRTHMONTH=AUGUST

您可以只加載文件. file.txt . file.txtsource file.txt 這將“加載”文件,即。 使其成為腳本的一部分,語法就是bash。 所以你可以:

. file.txt
echo "$FIRSTNAME"
echo "$LASTNAME" 
echo "$BIRTHMONTH"

這是在/ etc /中創建配置文件的常用方法,然后由腳本加載它們。 這就是為什么在許多/ etc /文件中,注釋以#開頭的原因。

筆記:

  1. 始終將變量括起來。 echo "$1" printArguments "$1" echo "$@" echo "$#" cat "$2" "$3" "$4" [ "$line" == ... ]在這里讀得很好
  2. 使用tr -d '\\n'刪除換行符
  3. ( )創建一個子shell,該子shell創建一個具有新變量且不與父級共享變量的新shell,請參見此處

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM