为什么某些用户功能无法被 bash 识别?

为什么某些用户功能无法被 bash 识别?

我可以定义一个函数如下:

myfunction () { ls -R "$1" ; }

进而

myfunction .

就可以了。

但如果我这么做

echo "myfunction ." | sh
echo "myfunction ." | bash

这些信息是:

sh: myfunction: not found  
bash: line 1: myfunction: command not found

为什么?如果不通过管道传输到 sh 或 bash,如何调用来自字符串的函数?

我知道有这个命令source,但我不知道什么时候应该使用source,什么时候sh应该使用bash。另外,我无法通过管道传输source。更令人困惑的是,这个命令.似乎与表示“当前目录”的“.”无关。

答案1

除了使用eval,您还可以使用export自己的函数,以便由子 shell 继承它:

myfunction () { ls -R "$1" ; }
export -f myfunction

进而

echo "myfunction ." | bash

就可以了。

echo "myfunction ." | sh可能不会,除非你的 /bin/sh 是 bash 的符号链接。

答案2

函数定义只在当前 bash 实例中有效。当你写

echo "myfunction ." | bash

您运行另一个 bash 实例。您需要在该实例中定义该函数。

如果您有一个包含函数名称和参数(如果需要,可以用引号引起来)的字符串,或者更一般地说,任何包含要执行的某些 shell 源代码的字符串,请使用内置函数eval

my_snippet='myfunction .'
eval "$my_snippet"

如果您在 中定义函数.bashrc,它们仅在交互式 shell 中可用,而不是在脚本中可用。

.命令(几乎)等同于,与当前目录的含义source无关。.

答案3

bashsh期望它们的参数是一个可执行文件,而不是一个字符串。

你可以使用以下命令执行字符串的内容

eval "myfunction ."

当您通过 shell 运行程序时,它通常会调用 的新实例bash(或shcshzsh等,视情况而定),继承所有原始 shell 的设置,并在新 shell 中运行自身。这样您就可以临时设置变量或更改设置,而不会干扰您的环境。

source执行命令将使其在你当前的 shell 中运行,因此它对环境所做的任何更改都将在命令退出时保留下来。.是 的同义词source

在大多数情况下,脚本会指定它要在哪个 shell 中运行(#!/bin/bash例如,在其第一行),并且您不需要明确调用 bash。

相关内容