簡體   English   中英

將輸出寫入shell中的多個文件

[英]write output to multiple files in shell

我在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

這里的問題是,輸出打印到控制台但不打印到新文件。 有人可以幫助我實現我的錯誤。

謝謝

我認為這會奏效

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

這不是你在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"

修復前面提到的問題(重新增加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.

這個清楚嗎? 如果沒有,請對其進行評論,然后我將對其進行編輯。 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;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM