簡體   English   中英

bash語言中使用的編程范例是什么?

[英]What are the programming paradigms used in the bash language?

在我嘗試過的一堆語言中,函數可以返回大量類型的值(整數,字符串,各種對象,返回函數的函數等),但在bash中,似乎唯一允許的類型是int,它不應該由其他函數使用,而是由shell本身知道一切是否正常(返回0),或者是否發生了一些錯誤,在這種情況下返回的值是錯誤代碼。

因此,例如,假設您要編寫一個想要將某些內容返回給另一個函數的函數。 你應該怎么做?

假設您要編寫一個findvideos函數,該函數返回在特定文件夾(及其子文件夾)中找到的每個視頻。 你想在另一個函數中使用該函數的結果,你會怎么做? 通過回聲和管道?

在編寫像這樣的小腳本時我一直堅持:

function firefoxcache {
    cache_dir=$1
    videos_dir=$2
    videos=$(findallvideos $videos_dir)
    for video in $videos; do
    echo cp $video $videos_dir/$(basename $video).flv
    done;
}

function findallvideos {
    videos=$(find $1 -exec file {} \; | grep -i $VIDEOS_REGX | cut -f1 -d:)
    #echo $videos
    return videos
}   

編輯

在Stackers的幫助下,這是工作代碼(減去愚蠢的雙斜線問題):

#!/usr/bin/env bash
function firefoxcache {
cache_dir=$1
videos_dir=$2
echo "$cache_dir", "$videos_dir"
echo
for video in $(findallvideos $cache_dir); do
echo cp $video $videos_dir/$(basename $video).flv
cp $video $videos_dir/$(basename $video).flv
done;
}

function findallvideos {
#echo findallvideos "$1"
for video in $(find $1 -exec file {} \; | grep -i $VIDEOS_REGX | cut -f1 -d:); do
echo $video;
done;
}

firefoxcache $1 $2

# cp /home/chaouche/.cache/mozilla/firefox/qmkhe4mr.default/Cache/4/B6/6AB61d01 VIDEOS//6AB61d01.flv
# cp /home/chaouche/.cache/mozilla/firefox/qmkhe4mr.default/Cache/4/28/A3524d01 VIDEOS//A3524d01.flv
# cp /home/chaouche/.cache/mozilla/firefox/qmkhe4mr.default/Cache/4/D2/29D4Ad01 VIDEOS//29D4Ad01.flv
# cp /home/chaouche/.cache/mozilla/firefox/qmkhe4mr.default/Cache/4/A1/15D75d01 VIDEOS//15D75d01.flv
# cp /home/chaouche/.cache/mozilla/firefox/qmkhe4mr.default/Cache/4/A3/2C971d01 VIDEOS//2C971d01.flv
# cp /home/chaouche/.cache/mozilla/firefox/qmkhe4mr.default/Cache/4/7E/E17D8d01 VIDEOS//E17D8d01.flv
# cp /home/chaouche/.cache/mozilla/firefox/qmkhe4mr.default/Cache/4/AC/5295Dd01 VIDEOS//5295Dd01.flv

Bash(和其他shell)正在使用流來傳遞值。 您引用的返回值與異常相關,而不是返回值。 如果返回值為≠0,則其語義通常是發生錯誤,並且調用者不應繼續,就好像什么都沒發生一樣。

另一方面,如果要返回一個值,則調用函數,腳本,子進程,無論應該打印哪個值返回到stdout 然后調用者可以捕獲該輸出並使用它:

square() {
  echo $[ $1 * $1 ]
}

a=4
b=$(square $a)
echo "$a squared is $b"

stdout是執行該操作的主流; 你可以使用像stderr這樣的其他流; 所以shell可以“返回”多個值。

當然,還有其他方面,例如子進程不一定必須終止父親閱讀並根據其輸出進行操作。 但我認為這對你的問題有點不合適。

關於你的具體用例,你必須找到一個解決方案,解決如何通過字節流傳輸值列表的古老問題。 一種解決方案是使用find Unix工具的print0選項。 它打印文件名,每個文件名都有一個終止零字節(這是Unix路徑中不能出現的少數幾個字符之一)。 然后,讀者過程必須期望這種格式。 例如,您可以使用xargs中的-0選項。

在你的情況下,我會使用read循環:

function findallfiles {
    find "$1" -print0
}

function findallvideos {
    findallfiles | while IFS='' read -d $'\0' f
      do
        [[ "$(file -b "$f")" =~ "$VIDEOS_REGX" ]] && printf "%s\0" "$f"
      done
}

function firefoxcache {
  cache_dir=$1
  videos_dir=$2
  findallvideos "$videos_dir" | while IFS='' read -d $'\0' video
    do
      echo cp "$video" "$videos_dir/$(basename "$video").flv"
    done
}

Shell腳本只能從函數類型返回整數值。 如果要從它們輸出字符串,則必須回顯該字符串,然后在分配給變量的子shell中捕獲該輸出。

例如

function foo()
{
    if [ "$1" = "hello" ] ; then
        echo "world";
        return 0;
    fi
    return 1;
}

a=$(foo "hello"); # a = world
echo $?;  # prints 0 - return values and exit status's are always assigned here.

a=$(foo); # a = empty string
echo $?;  # prints 1.

So for example, suppose you want to write a function that want to return something to another function. How should you do it ?

通過在函數stdout上寫一些東西,讓調用函數捕獲輸出。

例:

function foo () {
    echo "hello"
}

function fooCaller() {
    ret=$(foo)
    [[ "$ret" == "hello" ]] && echo "hello returned from function foo()"
}

暫無
暫無

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

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