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

时间:2012-10-27 01:10:58

标签: bash shell while-loop

我在File_A中有135个文件存储为135行(因此每行是一个长文本),我在File_B中有15个短语。我需要使用File_B中的匹配短语从File_A中提取一个句子及其之前的句子。 File_A-Line_1中提取的句子应输出到新文件File_1。类似地,从File_A-Line_2中提取的句子应该输出到新文件File_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

问题在于,输出正在打印到控制台而不是新文件。有人可以帮助我实现我的错误。

谢谢

4 个答案:

答案 0 :(得分:1)

我认为这会起作用

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

答案 1 :(得分:1)

这不是你在shell中增加变量的方法:

$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"

答案 2 :(得分:1)

修复前面提到的问题(重新递增i并滥用cat)会导致类似以下内容。注意,行date > file_$i用于调试,以确保每个输出文件在测试开始时都是新的。 :运算符是无操作符。表单<<<引入了“here-doc”。如果$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.

答案 3 :(得分:0)

这是否清楚?如果没有,请对其进行评论,然后我将对其进行编辑。 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;