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

fnx2tebb  于 2022-12-13  发布在  Shell
关注(0)|答案(5)|浏览(447)

我将135个文档存储为135行(因此每行都是一个长文本),而我在File_B中有15个短语。我需要从File_A中提取一个句子及其前面的短语,并在File_B中找到匹配的短语。从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

这里的问题是,输出被打印到控制台上,但没有打印到新文件中。有人能帮助我认识到我的错误吗?
谢谢你

ibps3vxo

ibps3vxo1#

这是清楚的吗?如果不,评论它,我会编辑它。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;
rqqzpn5f

rqqzpn5f2#

修复前面提到的问题(重新递增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包含以下内容的www.example.com:

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.
kpbpu008

kpbpu0083#

我想这会有用的

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
zdwk9cvp

zdwk9cvp4#

这不是在shell中递增变量的方式:

$i = $i + 1

它会尝试运行一个名称为$i当前值的命令。

let i=i+1

或者更精确地说,

let i+=1

这可能不是问题所在,但确实是个问题,而且会导致奇怪的行为。
我看到的唯一的另一件事是你的文件名周围缺少引号("$1""$2")。
同样,如果每一行都是一个文件名,就不需要cat;就做

<"$line" sed ...

如果每一行都是文件的内容而不是文件名,那么cat就完全错了,因为它试图找到一个文件名是那么长的文本。

<<<"$line" sed ...

EDIT此外,如果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"
ycl3bljg

ycl3bljg5#

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

相关问题