我有一个数字组成的文件。通常,每行包含一个数字。我想计算文件中以数字"0"开头的行数。如果是这样的话,我想做一些后处理。
虽然我能够正确检索相应的行号,但检索的行总数是不正确的。下面,我将发布我正在使用的代码。
linesToRemove=$(awk '/^0/ { print NR; }' ${inputFile});
# linesToRemove=$(grep -n "^0" ${inputFile} | cut -d":" -f1);
linesNr=${#linesToRemove} # <- here, the error
# linesNr=${#linesToRemove[@]} # <- here, the error
if [ "${linesNr}" -gt "0" ]; then
# do something here, e.g. remove corresponding lines.
awk -v n=$linesToRemove 'NR == n {next} {print}' ${anotherFile} > ${outputFile}
fi
另外,对于基于awk的命令,我如何使用shell变量?我尝试了下面的命令,但它不能正常工作,因为'myIndex'被解释为文本而不是变量。
linesToRemove=$(awk -v myIndex="$myIndex" '/^myIndex/ { print NR;}' ${inputFile});
给定${inputFile}
中以0
开头的行号,我想从${anotherFile}
中删除相应的行号。${inputFile}和${anotherFile}的例子如下:
// ${inputFile}
0
1
3
0
// ${anotherFile}
2.617300e+01 5.886700e+01 -1.894697e-01 1.251225e+02
5.707397e+01 2.214040e+02 8.607959e-02 1.229114e+02
1.725900e+01 1.734360e+02 -1.298053e-01 1.250318e+02
2.177940e+01 1.249531e+02 1.538853e-01 1.527150e+02
// ${outputFile}
5.707397e+01 2.214040e+02 8.607959e-02 1.229114e+02
1.725900e+01 1.734360e+02 -1.298053e-01 1.250318e+02
在上面的例子中,我需要从${anotherFile}
中删除0
和3
行,因为这些行对应于${inputFile}
中以0
开头的行。
如果您想计算文件中以0开头的行数,那么这一行是错误的。
linesToRemove=$(awk '/^0/ { print NR; }' ${inputFile});
上面说当行以0开头时打印行号,并且您的linesToRemove
变量将包含所有行号,而不是总行数。使用END{}
块捕获总数。如
linesToRemove=$(awk '/^0/ {c++}END{print c}' ${inputFile});
关于在awk中使用变量的第二个问题,请使用regex操作符~
。然后将myIndex
变量设置为包含^
锚
linesToRemove=$(awk -v myIndex="^$myIndex" '$0 ~ myIndex{ print NR;}' ${inputFile});
最后,如果你只想删除那些以0开头的行,那么只需删除
awk '/^0/{next}{print $0>FILENAME}' file
如果您想使用在输入文件中捕获的内容从另一个文件中删除行,这里有一种方法
paste -d"|" inputfile anotherfile | awk '!/^0/{gsub(/^.*|/,"");print}'
或者只有一个awk
命令
awk 'FNR==NR && /^0/{a[FNR]} NR>FNR && (!(FNR in a))' inputfile anotherfile
粗略解释:FNR==NR &&/^0/表示处理第一个文件整行以0开头,并将其行号放入数组a
。NR>FNR
表示处理下一个文件,如果行号不在数组中,则打印该行。查看gawk文档了解FNR,NR等的含义
我认为你必须这样做来分配一个数组:
linesToRemove=( $(awk '/^0/ { print NR; }' ${inputFile}) )
要获取元素的数量,可以这样做(就像在注释行中那样):
linesNr=${#linesToRemove[@]}
要从文件中删除这些行,可以这样做:
sedCmd=""
for lineNr in ${linesToRemove[@]}; do
sedCmd="$sedCmd;${lineNr}d"
done
sed "$sedCmd" ${anotherFile} > ${outputFile}
通常如果你这样做:
linesToRemove=$(awk '/^0/ { print NR; }' ${inputFile});
而不是:
linesToRemove=$(awk '/^0/ { print NR; }' ${inputFile});
linesNr=${#linesToRemove}
使用:
linesToRemove=$(awk '/^0/ { print NR; }' ${inputFile});
linesNr=${echo $linesToRemove|awk '{print NF}'}
POC:
cat temp.sh
#!/usr/bin/ksh
lines=$(awk '/^d/{print NR}' script.sh)
nooflines=$(echo $lines|awk '{print NF}')
echo $nooflines
torinoco!DBL:/oo_dgfqausr/test/dfqwrk12/vijay> temp.sh
8
torinoco!DBL:/oo_dgfqausr/test/dfqwrk12/vijay>
这在很大程度上取决于您正在进行的后处理,但是您真的需要实际计数吗?为什么不这样做呢?
<>之前如果grep ^0 $inputfile>/dev/null;然后至少有一行以0开头:fiGrep -v ^0 $inputfile | process-lines-without-lead - 0Grep ^0 $inputfile | process-lines-with-lead - 0之前或者,甚至只是:
<>之前如果grep ^0 $inputfile | process-lines-with-lead - 0;然后#一些后期处理:fi之前——编辑——
根据你在评论中所说的,我建议你采用另一种方法。如果我没理解错的话,你想读取文件a,寻找^0[0-9]*这样的行,然后从文件b中删除这些行号。如果文件变大了,那么一行一行地做是非常慢的。只做:
<>之前Cmd =$(grep '^0[0-9]*$' a | sed 's/$/d;/g')b .输入"$cmd"之前对cmd的赋值形成一个sed命令来删除行。在b上调用sed将省略这些行。您需要适当地重定向sed输出(可能重定向到一个临时文件,然后返回到b,或者如果您使用gnu sed,只需使用'sed -i')
鉴于这个问题有大量的编辑,似乎最容易开始一个新的答案。您的问题可以通过简单的一行代码解决:
<>之前$ sed "$(grep -n ^0 $inputFile | sed 's/:.*/d;/g')" $anotherFile> $outputFile