Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash unix查找命令错误_Bash_Unix_Find - Fatal编程技术网

Bash unix查找命令错误

Bash unix查找命令错误,bash,unix,find,Bash,Unix,Find,我的命令如下所示: P8.1 ~basicsys/win15/ex8/d1 cd 3 D A X F1 B #!/bin/sh dir="$1" shift line="$1" shift str="$1" shift for file in "$@"; do find "$dir" -type f -name "$file" -exec awk -v f="$file" -v l="$line" -v s="$str" -v c=0 'FNR == l { if(index($

我的命令如下所示:

P8.1 ~basicsys/win15/ex8/d1 cd 3 D A X F1 B
#!/bin/sh

dir="$1"
shift
line="$1"
shift
str="$1"
shift

for file in "$@"; do 
    find "$dir" -type f -name "$file" -exec awk -v f="$file" -v l="$line" -v s="$str" -v c=0 'FNR == l { if(index($0, s)) { ++c } nextfile } END { print f " " c }' '{}' +
done
所以我有三个参数:dir(保存目录)str(我正在寻找的字符串)num(行号)

我需要做的是检查文件并检查str是否出现在num行中

我需要打印如下内容:

[文件][str出现在目录树中某处的第num行的次数]

输出:

A 1
B 3
D 2
F1 1
X 0
通过调试,我发现我在执行
find
命令时遇到了问题

这是我的代码:

dir=$1
shift
str=$1
shift
num=$1
shift
echo 'head -$num | tail -1' >| getLine
echo -n "" >| out
chmod +x getLine

while [ $# -gt 0 ]
 do
  echo -n $1 " " >> out
  find $dir -type f -name $1 -exec getLine {} \; >| tmp
  egrep -c $str tmp >> out
shift
done
sort out
也许问题也出在
echo'head-$num | tail-1'

请参阅帮助:/
谢谢

我认为问题在于
getLine
脚本没有使用它的参数。它可能与

# also, variable expansion does not work in '' strings, like the comments noted.
echo "head -\"$num\" \"$1\" | tail -1" >| getLine
然而,我觉得这种方法相当丑陋。我会用awk这样做:

P8.1 ~basicsys/win15/ex8/d1 cd 3 D A X F1 B
#!/bin/sh

dir="$1"
shift
line="$1"
shift
str="$1"
shift

for file in "$@"; do 
    find "$dir" -type f -name "$file" -exec awk -v f="$file" -v l="$line" -v s="$str" -v c=0 'FNR == l { if(index($0, s)) { ++c } nextfile } END { print f " " c }' '{}' +
done
这有两个关键组件:一个是
find
调用中的
+
使其一次性将所有匹配文件传递给awk命令(有关精确的语义,请参阅
find
手册页)。另一个是awk脚本:

FNR == l {           # if the line is the lth in the file we're processing
  if(index($0, s)) { # and s is a substring of the line
    ++c              # increase the counter
  }
  nextfile           # short-circut to next file. This may fail with old versions
                     # of awk; it was introduced to the POSIX standard in 2012.
                     # It can be removed in that case, although that will make
                     # the script run more slowly (because it'll scan every file
                     # to the end)
}
END {                # at the very end
  print f " " c      # print the results.
}
此处,
l
s
f
通过
-v
选项设置为主脚本中的用户定义值。

首先 您必须用双引号替换引号
”,才能看到变量
$num
展开

不要使用
head | tail
,而是尝试
sed
: 我的目的(使用纯): 没有分叉和临时文件

!/bin/bash
dir=$1 str=$2 num=$3
班次3
名副其实
计数=0
在读取文件时;执行以下操作:

mapfile-s$[num-1]-tn 1 lineNum用双引号替换引号
,以便看到变量
$num
展开!你可以使用
sed$num'q;d'
代替
头|尾-n1
@F.Hauri谢谢!!!加上它作为答案,我会接受的,兄弟!类似于:
find$dir-typef-name$1-execsed$num'q;d'{}\
什么可以包含
$str
变量和“一行”(看起来像什么?
out
是什么?
$num
由用户控制。如果用户没有输入一个数字,这可能会以各种令人惊讶的方式打破。将未初始化的shell变量替换为sed代码已经够糟糕的了,但这甚至超出了双引号的shell字符串。@Wintermute您是对的,但由于在处理之前对条目进行清理可能会更好,因此可以使用相同的语法。当然,
sed“${num}q;d”
也会起作用,但对于示例,如果用户点击
w/etc/passwd;2
对于
$num
,使用双引号只会有助于此攻击尝试…我的一般方法/建议是:当您试图将shell变量放入sed代码中时,尝试使用
awk-v var=“$var”
;它只会在类型不匹配时出错,而且在脚本语言中,您将尽可能安全。Sed可能比awk更性感,但不管你从哪个角度看,用户可修改的代码都很讨厌,而且Sed能做的很多/大部分事情都很容易翻译成awk。缺少的背景有时令人烦恼,但这并不需要它们。在这种情况下,
awk-v line=“$num”'FNR==line'
的作用与
sed相同,“$num q;d”
@Wintermute
sed
awk
快得多。对于许多调用,它可能变得很重要。排除特殊情况,正确性比速度更重要。老实说,当性能变得至关重要时,关键是停止编写shell脚本。