我希望我的bash脚本检查运行它的目录的名称。类似的东西:
#!/bin/bash
path=eval 'pwd'
dirname=eval 'basename $path'
但它不起作用:我得到了
./foo.sh: line 5: basename $path: command not found
我该如何解决?此外,一旦我得到dirname包含正确的dirname,我就想将其转换为小写,以进行测试。我可以在命令行上使用awk执行此操作:
echo $dirname | awk '{print tolower($0)}'
但是如何将返回值捕获到变量中?提前谢谢你,
最好的问候
塞尔吉奥
答案 0 :(得分:3)
为什么不使用:
#!/bin/bash
path=`pwd`
dirname=`basename $path | awk '{print tolower($0)}'`
或者如果你想把它作为一个班轮:
dirname=`pwd | xargs basename | awk '{print tolower($0)}'`
答案 1 :(得分:2)
您可以将其重写为
dirname=eval "basename $path"
使用单引号,您不会进行shell扩展,但希望$path
扩展。
BTW:我建议使用
path=$(basename $path)
如果您执行类似
的操作,它会更通用,更易读path=$(basename $(pwd))
或获取小写结果
path=$(basename $(pwd) | awk '{print tolower($0)}')
或
path=$(basename $(pwd) | tr 'A-Z' 'a-z' )
答案 2 :(得分:2)
表格
x=y cmd
表示暂时将环境变量x
设置为值y
,然后运行cmd
,这就是解释这些行的方式:
path=eval 'pwd'
dirname=eval 'basename $path'
也就是说,它们没有按照您的期望进行操作,而是将环境变量设置为文字值eval
,然后运行(或无法找到)命令。正如其他人所说,将命令结果插入字符串的方法是将其放在$(...)
(首选)或`...`
(遗留)中。并且,作为一般规则,用双引号将它们包装起来更安全(因为在引号中包装任何插值引用更安全)。
path="$(pwd)"
dirname="$(basename "$path")"
(从技术上讲,在这种情况下,外部引号并非绝对必要。但是,我认为它仍然是一个好习惯。)
答案 3 :(得分:0)
B=$(echo "Some text that has CAPITAL letters " | awk '{print tolower($0)}')
答案 4 :(得分:0)
eval执行传递给它的命令,但它只返回命令退出状态代码,因此你无法在set运算符中真正使用它。将命令嵌入到set运算符中以使用正确的单引号或$()
所以脚本将如下所示:
#!/bin/bash
curr_path=$(pwd)
echo $curr_path
curr_dir=$(basename $curr_path)
echo $curr_dir
echo $curr_dir | awk '{print tolower($0)}'
答案 5 :(得分:0)
您的代码不起作用,因为您使用单引号而不是双引号。单引号可防止变量扩展,因此$path
不会扩展到您要使用的路径中,而是按原样使用,因为它是一个字符串。
你的awk调用也不会出于同样的原因。
虽然你可以解决用双引号替换单引号的问题,如下所示:
#!/bin/bash
path=eval "pwd"
dirname=eval "basename $path"
在这种情况下,我建议使用严重的重音(). There's no reason to use
eval`。另外,您还可以使用它来收集您感兴趣的返回值:
#!/bin/bash
path=`pwd`
dirname=`basename $path`
variable=`echo $dirname | awk "{print tolower($0)}"`
答案 6 :(得分:0)
这里是我对What platform independent way to find directory of shell executable in shell script?的回答的摘录,除了小写部分之外,它本身完全回答了你的问题,在我看来,这个问题在其他答案中得到了很好的解决。
我的答案的独特之处在于,当我尝试为其他问题编写代码时,我遇到了您确切的问题 - 如何将功能的结果存储在变量? 嗯,正如你所看到的,在一些帮助下,我找到了一个非常简单且非常强大的解决方案:
我可以将函数传递给某种 messenger变量,并取消引用任何明确使用结果函数的$1
名eval
的名称必要时,并且在函数例程完成后,我使用eval
和一个反向引用技巧来为我的信使变量分配我想要的值,而不必知道它的名字。
完全披露,虽然这是我的问题的解决方案,但我的解决方案 我之前有几次访问过那里,但是他的一些描述虽然可能很精彩,但是我的联盟还有一点,所以我认为如果在前一段中包含我自己的版本,其他人可能会受益。虽然我一旦理解这一点非常简单,特别是对于这一点,我不得不长时间地思考它是如何工作的。无论如何,您可以在Rich's sh tricks找到更多内容,我也在我自己的答案的摘录中摘录了他的页面的相关部分。
... 的摘录:强> ...
虽然还不是严格的POSIX,realpath 是自2012年以来的GNU核心应用。完全披露:在我info coreutils
TOC注意到之前从未听说过它,并立即想到了[链接]问题,但是使用以下函数应该可靠,(很快就是POSIXLY?),我希望,有效率的
为其来电者提供绝对来源的$0
:
% _abs_0() {
> o1="${1%%/*}"; ${o1:="${1}"}; ${o1:=`realpath "${1}"`}; eval "$1=\${o1}";
> }
% _abs_0 ${abs0:="${0}"} ; printf %s\\n "${abs0}"
/no/more/dots/in/your/path2.sh
编辑:值得强调的是,此解决方案使用POSIX parameter expansion在尝试执行此操作之前首先检查路径是否实际需要扩展和解析。这应该通过信使变量 返回绝对来源的$0
(但值得注意的例外是它会将symlinks
)保留为有效< / strong>我可以想象它可以完成路径是否已经绝对。
...
( 次要编辑 :在文档中找到realpath
之前,我至少减少了我的[以下版本]的版本依赖于时间字段[就像它在第一个ps
命令中所做的那样],但是,公平警告,在测试之后我不太相信ps
在其命令路径扩展能力方面是完全可靠的)
另一方面,你可以这样做:
ps ww -fp $$ | grep -Eo '/[^:]*'"${0#*/}"
eval "abs0=${`ps ww -fp $$ | grep -Eo ' /'`#?}"
... 来自Rich's sh tricks: ...
从shell函数返回字符串
从上面的命令替换缺陷中可以看出,stdout不是shell函数将字符串返回给调用者的好途径,除非输出采用尾随换行无关紧要的格式。当然,这种做法对于处理任意字符串的函数是不可接受的。那么,可以做些什么呢?
试试这个:
func () {
body here
eval "$1=\${foo}"
}
当然${foo}
可以替换为任何类型的替换。这里的关键技巧是评估线和转义的使用。当eval的参数由主命令解析器构造时,“$1”
被扩展。但是“${foo}”
在此阶段尚未展开,因为“$”
已被引用。相反,当eval评估其参数时,它会被扩展。如果不清楚为什么这很重要,请考虑以下情况如何:
foo='hello ; rm -rf /'
dest=bar
eval "$dest=$foo"
但当然以下版本是绝对安全的:
foo='hello ; rm -rf /'
dest=bar
eval "$dest=\$foo"
请注意,在原始示例中,“$1”
用于允许调用者将目标变量名称作为函数的参数传递。如果您的函数需要使用shift命令,例如将剩余的参数作为“$@”
处理,那么将“$1”
的值保存在函数开头的临时变量中可能很有用。