简体   繁体   English

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

[英]Is it possible to set variable in pipeline?

I have a big txt file which I want to edit in pipeline. 我有一个很大的txt文件,我想在管道中进行编辑。 But on same place in pipeline I want to set number of lines in variable $nol. 但是在管道的同一位置,我想在变量$ nol中设置行数。 I just want to see sintax how could I set variable in pipeline like: 我只想看看sintax我如何在管道中设置变量,例如:

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

That after second pipe is very wrong, but how can I do it in bash? 在第二个管道之后那是非常错误的,但是我该如何用bash进行呢?

One of solutions is: 解决方案之一是:

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

but I don't want to do script the same thing twice, bec I have more pipes then here. 但是我不想重复两次编写相同的脚本,因为我这里的管道更多。

I musn't use awk or sed... 我不使用awk或sed ...

You can set a variable in a particular link of a pipeline, but that's not very useful since only that particular link will be affected by it. 您可以在管道的特定链接中设置变量,但这并不是很有用,因为只有该特定链接会受到它的影响。

I recommend simply using a temporary file. 我建议只使用一个临时文件。

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

You can avoid the temporary file with tee and a named pipe, but it probably won't perform much better (it may even perform worse). 您可以避免使用带有tee和命名管道的临时文件,但是它的性能可能不会更好(它甚至可能更差)。

Looks to me like you're asking how to avoid stepping through your file twice, just to get both word and line count. 在我看来,您在询问如何避免单步执行两次文件,只是为了获得字数和行数。

Bash lets you read variables, and wc can produce all the numbers you need at once. Bash允许您读取变量,而wc可以一次生成您需要的所有数字。

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

So to start... 所以开始...

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

This populates the three variables based on input generated from process substitution . 这将根据流程替换生成的输入填充三个变量。

But your question includes another partial command line which I think you intend as: 但是您的问题包括另一个部分命令行,我认为您打算这样做:

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

This is markedly different from the word count of your first command line, so you can't use a single wc instance to generate both. 这与您的第一个命令行的字数明显不同,因此您不能使用单个wc实例来生成两者。 Instead, one option might be to put your functionality into a script that does both functions at once: 相反,一种选择可能是将您的功能放入可以同时执行两个功能的脚本中:

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

You can use a tee and then write it to a file which you use later: 您可以使用tee ,然后将其写入到以后使用的文件中:

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

Or you can use it the other way around: 或者,您也可以反过来使用它:

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

UPDATE: 更新:

Took a minute but I got it... 花了一点时间但我明白了...

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

PREVIOUS: 以前:

The only way I can think to do this is storing in variables and calling back. 我能想到的唯一方法是将其存储在变量中并进行回调。 You would not execute the command more than one time. 您最多只能执行一次命令。 You would just store the output in variables along the way. 您只需要沿途将输出存储在变量中。

aCommand=($(cat ${!#} | tr ' ' '\n'));sLineCount=$(echo ${#aCommand[@]});echo ${aCommand[@]} | sort | uniq -c ...
  • aCommand will store the results of the first set of commands in an array aCommand会将第一组命令的结果存储在数组中
  • sLineCount will count the elements (lines) in the array sLineCount将对数组中的元素(线)进行计数
  • ;... echo the array elements and continue the commands from there. ; ...回显数组元素,然后从那里继续执行命令。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM