[英]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.