bash语言中使用的编程范式是什么



在我尝试过的一堆语言中,函数可以返回相当数量的类型(整数、字符串、各种对象、返回函数的函数等)的值,但在 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 $'' f
      do
        [[ "$(file -b "$f")" =~ "$VIDEOS_REGX" ]] && printf "%s" "$f"
      done
}
function firefoxcache {
  cache_dir=$1
  videos_dir=$2
  findallvideos "$videos_dir" | while IFS='' read -d $'' video
    do
      echo cp "$video" "$videos_dir/$(basename "$video").flv"
    done
}

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()"
}

最新更新