在 csh 中将变量设置为包含元字符、find 和另一个变量的字符串时出现问题

在 csh 中将变量设置为包含元字符、find 和另一个变量的字符串时出现问题

我正在一个项目中使用 csh(抱歉,被迫使用它),并且我的脚本的一个组件在其大部分功能中使用了以下内容的变体:

find . -maxdepth 1 -not -type d | awk '{gsub(/.\//,"")}1' | grep $userID

这按我的脚本中的预期工作,但我需要将其设置为变量,以便我可以更改表达式和 grep 结果(有一个修改此字符串的大型 switch 语句)。我尝试了很多方法,但似乎无法让它发挥作用。因此,我不仅使用 CSH,还将命令加载到变量中(我不,不,再次抱歉),但对于这个非常具体的情况,如果可能的话,我想尝试使其工作。我觉得这只是一个引用/格式问题,否则我会完全放弃它。

这是我所做的:

双引号:

set findString = "find . -maxdepth 1 -not -type d | awk '{gsub(/.\//,"")}1' | grep $userID"

这个回声很好,但是当执行 find 时,我收到以下错误:

查找:路径必须位于表达式之前:|

我意识到 shell 会在执行命令之前尝试扩展它,但我不确定如何解决这个问题(我似乎无法引用它以使其正常工作)。我尝试通过以下方式将其放在引号中:

set findString = "find . -maxdepth 1 -not -type d \"|\" awk '{gsub(/.\//,"")}1' | grep $userID"
set findString = "find . -maxdepth 1 -not -type d \"| awk '{gsub(/.\//,"")}1' | grep $userID\""
set findString = "find \". -maxdepth 1 -not -type d | awk '{gsub(/.\//,"")}1' | grep $userID\""
set findString = "\"find . -maxdepth 1 -not -type d | awk '{gsub(/.\//,"")}1 | grep $userID'\""

并收到以下每项:

无与伦比”。

然后我尝试了单引号,但似乎无法让它回显:

set findString = 'find . -maxdepth 1 -not -type d | awk \'{gsub(/.\//,"")}1\' | grep $userID'
echo $findString

再次:无与伦比的'。

此时,我再次尝试使用双引号,但转义了所有 csh 元字符:

set findString = "find\ .\ \-maxdepth\ 1\ \-not\ \-type\ d\ \|\ awk\ \'\{gsub(/.\\//,\"\"\)}1\'\ \|\ grep\ \$userID"

没有。所以我找到了另一个引用的线程这份有用的文件引用,并尝试以不同的方式实现它。我最终取出find了变量,并将变量中的其余字符串加载为搜索选项。我还剥掉了grep管子,试图将其归零。它看起来像:

set findString = ( \( -maxdepth 1 -not -type d | awk '{gsub(/.\//,"")}1' \) )
echo $findString
find . "${findString}"

尽管find可以运行,但它无法正确评估。我觉得肯定有办法做到这一点。

我被困住了。我将不胜感激对此的任何帮助,并再次为使用 CSH 犯下双重暴行并将此命令字符串加载到 var 表示歉意。

答案1

我认为您不能将 a 放入|变量中并将其解释为在变量扩展后不使用eval.

因此,您可以做的是将参数放入find一个变量,并将 awk 命令放入另一个变量:

这似乎对我有用(在 tcsh 上):

> mkdir dir; touch dir/file
> set findopts = '-type f'
> set awkcmd = '{gsub(/.\//,"")}1'
> find . $findopts | awk "$awkcmd" 
difile

不过,./匹配任何后跟斜杠的字符,所以也许您也想转义点:

> set awkcmd = '{gsub(/\.\//,"")}1'
> find . $findopts | awk "$awkcmd"
dir/file

或者使用eval,如果你坚持的话:

> set cmd = 'find . -type f | awk '\''{gsub(/\.\//,"" ) }1'\'
> eval "$cmd"
dir/file

坦率地说,我不知道 csh 的引用微妙之处(并且没有兴趣去了解)。上面的工作方式似乎与 POSIX-like shell 类似,但请自行检查。

相关内容