如何利用shell脚本中的eval命令来构造"智能"命令
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何利用shell脚本中的eval命令来构造"智能"命令相关的知识,希望对你有一定的参考价值。
参考技术A
今天主要介绍一个shell脚本中比较少见的命令--eval
功能说明 :重新运算求出参数的内容。
语 法 :eval [参数]
补充说明 :eval可读取一连串的参数,然后再依参数本身的特性来执行。
参 数 :参数不限数目,彼此之间用分号分开。
eval命令将会首先扫描命令行进行所有的替换,然后再执行命令。该命令使用于那些一次扫描无法实现其功能的变量。该命令对变量进行两次扫描。这些需要进行两次扫描的变量有时候被称为复杂变量。eval也可以用于回显简单变量,不一定是复杂变量。
eval的作用是再次执行命令行处理,也就是说,对一个命令行,执行两次命令行处理。这个命令要用好,就要费一定的功夫。下面用几个例子帮助大家理解下。
1、eval一个命令
eval echo相当于echo
2、两次扫描
该命令适用于依次扫描无法完成其功能的变量。
第一步:对eval后面的命令进行扫描,执行变量替换,普通命令保留
第二步:执行变量替换后的命令串
3、获得最后一个参数
4、用eval技巧实现shell的控制结构for
用eval技巧实现shell的控制结构for
输出结果:
注意:bash里有两个很特殊的变量,它们保存了参数列表。
这里我使用了函数递归以及eval实现了for结构。
当执行eval $@时,它经历了步骤如下:
第1步,分割成eval $@
第6步,扩展$@为hostname
第11步,找到内置命令eval
重复一次命令行处理,第11步,找到hostname命令,执行。
eval是对Bash Shell命令行处理规则的灵活应用,进而构造"智能"命令实现复杂的功能。上面提及的命令是eval其中一个很普通的应用,它重复了1次命令行参数传递过程,纯粹地执行命令的命令。其实它是bash的难点,是高级bash程序员的必修技能。
如何在 bash shell 脚本中的 perl 命令调用中使用 shell 变量?
【中文标题】如何在 bash shell 脚本中的 perl 命令调用中使用 shell 变量?【英文标题】:How to use shell variables in perl command call in a bash shell script? 【发布时间】:2012-10-17 02:52:04 【问题描述】:如何在 bash shell 脚本的 perl 命令调用中使用 shell 变量?
我的 shell 脚本中有一个 perl 命令来计算日期 -1。
如何在 perl 命令调用中使用$myDate
?
这是我脚本中的部分:
myDate='10/10/2012'
Dt=$(perl -e 'use POSIX;print strftime '%m/%d/%y', localtime time-86400;")
我想用$myDate
代替%m/%d/%y
。
任何帮助将不胜感激。
谢谢。
【问题讨论】:
用myDate
的值替换'%m/%d/%y'
没有任何意义,除非您将myDate
的值更改为%m/%d/%y
之类的值。请适当地解决您的问题。
【参考方案1】:
来自 shell 的变量在 Perl 的 %ENV
哈希中可用。对于bash
(和其他一些shell),您需要采取额外的步骤“导出”您的shell 变量,以便子进程可以看到它。
mydate=10/10/2012
export mydate
perl -e 'print "my date is $ENVmydate\n"'
【讨论】:
这是一个规则的简单答案。上面的只是看起来像一些我无法理解的复杂代码 另外,如果您运行perl -p
,那么它会将--
解释为文件名,因此只能在此类脚本中使用$ENV
@henley-chiu :公平地对待@ikegami 接受的答案,使用“--arg”方法可以避免污染 bash 环境,而在 bash 函数或别名中使用 export
意味着运行带有export
的函数/别名将导致在 bash 会话期间设置“mydate”。【参考方案2】:
与将值传递给任何其他程序的方式相同:将其作为 arg 传递。 (您可能很想生成 Perl 代码,但这是个坏主意。)
Dt=$( perl -MPOSIX -e'print strftime $ARGV[0], localtime time-86400;' -- "$myDate" )
请注意,代码并不总是返回昨天的日期(因为并非所有日期都有 86400 秒)。为此,你会想要
Dt=$( perl -MPOSIX -e'my @d = localtime time-86400; --$d[4]; print strftime $ARGV[0], @d;' -- "$myDate" )
或
Dt=$( perl -MDateTime -e'print DateTime->today(time_zone => "local")->subtract(days => 1)->strftime($ARGV[0]);' -- "$myDate" )
或者干脆
Dt=$( date --date='1 day ago' +"$myDate" )
【讨论】:
这篇文章假设你想使用myDate
作为你所说的格式说明符,这意味着myDate
实际上包含%m/%d/%y
之类的东西。【参考方案3】:
在 5.24 版本中使用 "
代替 '
也会将 shell 变量传递给 perl。
mydate=22/6/2016
perl -e "print $mydate"
【讨论】:
这是池上在接受的答案中建议反对的,有充分的理由。如果您可以完全控制mydate
并了解您在做什么,那么将其作为 Perl 代码进行插值就可以了……但在这种情况下肯定不是这样,因此这个 sn-p 将产生不稳定的输出 0.00181878306878307
。 【参考方案4】:
为什么不这样:
$ENV'PATH' = $ENV'PATH'.":"."/additional/path";
【讨论】:
【参考方案5】:对我来说,我需要使用$ENV'VARIABLE'
将shell 中的VARIABLE
传递给Perl。我不知道为什么只是 $ENVVARIABLE
不起作用。
例如,
在 Bash 中:
#!/bin/bash -l
VARIABLE=1
export VARIABLE
perl example.pl
在 Perl 中:
#!/usr/bin/perl -w
print "my number is " . $ENV'VARIABLE'
【讨论】:
【参考方案6】:与将值传递给任何其他程序的方式相同:将其作为 arg 传递。 (您可能很想生成 Perl 代码,但这是个坏主意。)
Dt=$( perl -MPOSIX -e'my($m,$d,$y) = split qr/, $ARGV[0]; --$d; print strftime "%m/%d/%y", 0,0,0, $d,$m-1,$y-1900;' -- "$myDate" )
【讨论】:
这篇文章假设你真的想使用myDate
作为修改日期而不是格式说明符。以上是关于如何利用shell脚本中的eval命令来构造"智能"命令的主要内容,如果未能解决你的问题,请参考以下文章