是否可以在管道中设置变量?

Is it possible to set variable in pipeline?

我有一个很大的 txt 文件,我想在管道中进行编辑。但是在管道的同一个地方,我想在变量 $nol 中设置行数。我只想看看 sintax 如何在管道中设置变量,如:

  cat ${!#} | tr ' ' '\n'| grep . ; $nol=wc -l | sort | uniq -c ...

在第二个管道之后是非常错误的,但是在 bash 中我该怎么做呢?

其中一个解决方案是:

nol=$(cat ${!#} | tr ' ' '\n'| grep . | wc -l)
pipeline all from the start again

但我不想对同一件事执行两次脚本,因为我这里的管道更多。

我不能使用 awk 或 sed...

您可以在管道的特定 link 中设置变量,但这不是很有用,因为只有那个特定的 link 会受到它的影响。

我建议只使用一个临时文件。

set -e
trap 'rm -f "$tmpf"' EXIT
tmpf=`mktemp`
cat ${!#} | tr ' ' '\n'| grep . | sort > "$tmpf"
nol="$(wc "$tmpf")"
< "$tmpf" uniq -c ...

您可以使用 tee 和命名管道避免使用临时文件,但它的性能可能不会好多少(甚至可能性能更差)。

在我看来,您好像在问如何避免两次单步执行文件,只是为了同时计算字数和行数。

Bash让你读取变量,wc可以一次产生你需要的所有数字。

NAME
     wc -- word, line, character, and byte count

那么开始...

read words line chars < <( wc < ${!#} )

这会根据从 process substitution 生成的输入填充三个变量。

但是您的问题包括另一个部分命令行,我认为您打算将其作为:

nol=$( sort -u ${!#} | wc -l )

这与您的第一个命令行的字数统计明显不同,因此您不能使用单个 wc 实例来生成两者。相反,一种选择可能是将您的功能放入同时执行这两个功能的脚本中:

read words uniques < <(
awk '
      {
        words += NF
        for (i=1; i<=NF; i++) { unique[$i] }
      }
      END {
        print words,length(unique)
      }
    ' ${!#}
)

您可以使用 tee 然后将其写入您稍后使用的文件:

tempfile="xyz"
tr ' ' '\n' < "${!#}" | grep '.' | tee > "$tempfile" | sort | uniq -c ...
nol=$(wc -l "$tempfile")

或者您可以反过来使用它:

nol=$(tr ' ' '\n' < "${!#}" | grep '.' \
  | tee >(sort | uniq -c ... > /dev/tty) | wc -l

更新:

花了一分钟,但我明白了...

cat ${!#} | tr ' ' '\n'| tee >(nol=$(wc -l)) | sort | uniq -c ...

上一个:

我能想到的唯一方法是存储在变量中并回调。您不会多次执行该命令。您只需将输出存储在变量中。

aCommand=($(cat ${!#} | tr ' ' '\n'));sLineCount=$(echo ${#aCommand[@]});echo ${aCommand[@]} | sort | uniq -c ...
  • aCommand 将第一组命令的结果存储在一个数组中
  • sLineCount 将计算数组中的元素(行)
  • ;...回显数组元素并从那里继续执行命令。