将命令的输出分配给 shell 变量并获取变量大小



我有一个数字组成的文件。通常,每行包含一个数字。我想计算文件中以数字"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}中删除03行,因为这些行对应于${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开头,并将其行号放入数组aNR>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

相关内容

  • 没有找到相关文章

最新更新