将输出写入Shell中的多个文件



我在file_a中存储了135个文档为135行(因此每行都是长的文本),我在file_b中有15个短语。我需要从file_b中的匹配短语从file_a提取句子及其之前。从file_a-line_1提取的句子应输出到新的文件file_1。同样,从file_a-line_2提取的句子应输出到新的文件_2,依此类推,直到我从所有行中提取匹配句子为止。我使用以下代码

做到了这一点
i=1
while read line; do
 while read row; do
   cat "$line" | sed 's/./.n/g' | grep -i -B 1 "$row"  | tr -d 'n' |  sed 's/--/n/g'    >> file_$i
 done < $2 
 $i = $i+1;
done < $1

这里的问题是,输出被打印到控制台上,而不是在新文件上。有人可以帮助我意识到自己的错误。

谢谢

这很清楚吗?如果没有,请对其发表评论,我将编辑它。BASH输出重定向示例:

echo "some text" >file.txt;
#here we add on to the end of the file instead of overwriting the file
echo "some additional text" >>file.txt;
#put something in two files and output it
echo "two files and console" | tee file1.txt | tee file2.txt;
#put something in two files and output nothing
echo "just two files" | tee file1.txt >file2.txt;

解决以前提到的问题(重新递增icat的滥用)会导致以下内容。请注意,该行date > file_$i在那里进行调试,以确保每个输出文件在测试开始时都是新的。:运算符是无操作的。<<<表格引入了"此处介绍"。如果$lines的内容是文件名,而不是作为问题中指定的文档,而是使用<"$lines"代替<<<"$lines"

#!/bin/bash
i=1
while read line; do
    date > file_$i
    while read row; do
    sed 's/./.n/g' <<< "$line" | grep -iB1 "$row" | tr -d 'n' |  sed 's/--/n/g' >> file_$i
    done < $2 
    : $((i++))
done < $1

给定的splitdoc.data包含以下内容:

This is doc 1.  I am 1 fine.  How are you, 1.? Ok. Hello 1.--  Go away now.
This is doc 2.  I am 2 fine.  How are you, 2.? Ok. Hello 2.--  Go away now.
This is doc 3.  I am 3 fine.  How are you, 3.? Ok. Hello 3.--  Go away now.
This is doc 4.  I am 4 fine.  How are you, 4.? Ok. Hello 4.--  Go away now. 

和splitdoc.tags具有以下内容:

How are you
Go away now

然后命令

./splitdoc.sh splitdoc.data splitdoc.tags ; head file_*

生产:

==> file_1 <==
Fri Oct 26 19:42:00 MDT 2012
  I am 1 fine.  How are you, 1. Hello 1.
  Go away now.
==> file_2 <==
Fri Oct 26 19:42:00 MDT 2012
  I am 2 fine.  How are you, 2. Hello 2.
  Go away now.
==> file_3 <==
Fri Oct 26 19:42:00 MDT 2012
  I am 3 fine.  How are you, 3. Hello 3.
  Go away now.

我认为这会起作用

i=1
while read line; do
 while read row; do
   echo "$line" | sed 's/./.n/g' | grep -i -B 1 "$row"  | tr -d 'n' |  sed 's/--/n/g' >> file_$i
 done < $2 
 $i = $i+1;
done < $1 
a=0 
while read line; do 
a=$(($a+1)); 
while read row; do
    echo "$line" | sed 's/./.n/g' | grep -i -B 1 "$row" | tr -d 'n' | sed 's/--/n/g' >> file_$a done < $2 done < $1

这不是您在外壳中增加变量的方式:

$i = $i + 1

试图运行名称是$i的当前值的命令。您想要这个:

let i=i+1

或更简单地,

let i+=1

这可能不是问题,但这是一个问题,它可能导致奇怪的行为。

我唯一看到的另一件事是您的文件名缺乏引号("$1""$2")。

另外,如果每行都是文件名,则不需要cat;只是做

<"$line" sed ...

如果每行是文件的内容而不是名称的内容,则cat是完全错误的,因为它试图找到一个名称为大文本的文件。您可以使用此方法:

<<<"$line" sed ...

编辑,如果FileB中没有那么多行,您可能可以避免在Filea中列出的每个文件中一遍又一遍地阅读它。只需立即将所有FileB读取到内存中:

IFS=$'n' rows=($(<"$2"))
let i=0
while read line; do
  for row in "${rows[@]}"; do
    <<<"$line" sed 's/./.n/g' | grep -i -B 1 "$row"  | 
             tr -d 'n' |  sed 's/--/n/g' >> file_$i
  done 
  let i+=1
done < "$1"

实际上,您甚至可以在一个Grep中进行操作:

pat=''
while read row; do
  pat="${pat:+$pat|}$row"
done <"$2"
let i=0
while read line; do
  <<<"$line" sed 's/./.n/g' | egrep -i -B 1 "$pat"  | 
             tr -d 'n' |  sed 's/--/n/g' >"file_$i"
let i+=1
done < "$1"

tee实际上接受多个文件参数,因此很简单:

# from file
tee 1.txt 2.txt 3.txt <0.txt
# from string
tee 1.txt 2.txt 3.txt <<<'text'
# from heredoc
tee 1.txt 2.txt 3.txt <<'EOF'
line
line
line
EOF
# from pipeline
command | tee 1.txt 2.txt 3.txt

相关内容

  • 没有找到相关文章

最新更新