简体   繁体   English

在 bash 脚本中重用虚拟文件

[英]reuse virtual files in bash script

What I am trying to do is run a bash script that looks somewhat like this:我想要做的是运行一个看起来有点像这样的 bash 脚本:

#!/usr/bin/bash

only1=$(comm -23 $1 $2 | wc -l)
only2=$(comm -13 $1 $2 | wc -l)
common=$(comm -12 $1 $2 | wc -l)

echo -e "${only1} only in $1"
echo -e "${only2} only in $2"
echo -e "${common} in both"

If I execute the script as script.sh file1 file2 it works fine.如果我将脚本作为script.sh file1 file2执行,它可以正常工作。 However, if I use it as script.sh <(grep 'foo' file1) <(grep 'foo' file2) it fails because the virtual files of the kind dev/fd/62 are only available for the first command ( only1 in the script).但是,如果我将它用作script.sh <(grep 'foo' file1) <(grep 'foo' file2)它会失败,因为dev/fd/62类型的虚拟文件仅可用于第一个命令( only1 in剧本)。 The output is: output 是:

262 only in /dev/fd/63
0 only in /dev/fd/62
0 in both

Is there a way to make these virtual files available to all of the commands in the script?有没有办法让脚本中的所有命令都可以使用这些虚拟文件?

The issue here is that the first invocation of comm will read to the end of both input files.这里的问题是第一次调用comm将读取到两个输入文件的末尾。

As you'd like to be able to provide pipes as the input (instead of a " real file), you'll need read the inputs once only, and then provide that as input to the subsequent commands... With pipes, as soon as data is read, it's gone and isn't coming back.由于您希望能够提供管道作为输入(而不是“真实文件”),因此您只需读取一次输入,然后将其作为输入提供给后续命令......使用管道,如一旦数据被读取,它就消失了,不会再回来了。

For example:例如:

#!/bin/bash -eu

# cleanup temporary files on exit
trap 'rm ${TMP_FILE1:-} ${TMP_FILE2:-}' EXIT

TMP_FILE1=$(mktemp)
cat < $1 > $TMP_FILE1

TMP_FILE2=$(mktemp)
cat < $2 > $TMP_FILE2

only1=$(comm -23 $TMP_FILE1 $TMP_FILE2 | wc -l)
only2=$(comm -13 $TMP_FILE1 $TMP_FILE2 | wc -l)
common=$(comm -12 $TMP_FILE1 $TMP_FILE2 | wc -l)

echo -e "${only1} only in $1"
echo -e "${only2} only in $2"
echo -e "${common} in both"

If your files are small enough, then you can get away with reading them into variables:如果您的文件足够小,那么您可以将它们读入变量:

#!/bin/bash -eu

FILE1=$( < $1 )
FILE2=$( < $2 )

only1=$(comm -23 <( echo "$FILE1" ) <( echo "$FILE2" ) | wc -l)
only2=$(comm -13 <( echo "$FILE1" ) <( echo "$FILE2" ) | wc -l)
common=$(comm -12 <( echo "$FILE1" ) <( echo "$FILE2" ) | wc -l)

echo -e "${only1} only in $1"
echo -e "${only2} only in $2"
echo -e "${common} in both"

Please also note that comm only works on sorted data... which means you probably want to use sort on the inputs, unless you are fully aware of the consequences of using unsorted inputs.另请注意, comm仅适用于已排序的数据......这意味着您可能希望对输入使用sort ,除非您完全了解使用未排序输入的后果。

sort < $1 > $TMP_FILE1
FILE1=$( sort < $1 )

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

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