我有2个文件:
File_1.txt:
John
Mary
Harry
Bill
File_2.txt:
My name is ID, and I am on line NR of file 1.
我想创建四个看起来像这样的文件:
Output_file_1.txt:
My name is John, and I am on line 1 of file 1.
Output_file_2.txt:
My name is Mary, and I am on line 2 of file 1.
Output_file_3.txt:
My name is Harry, and I am on line 3 of file 1.
Output_file_4.txt:
My name is Bill, and I am on line 4 of file 1.
通常我会使用以下sed命令来执行此操作:
for q in John Mary Harry Bill
do
sed 's/ID/'${q}'/g' File_2.txt > Output_file.txt
done
但是这只会替换名称的ID,而不包括File_1.txt的行号。不幸的是,我的bash技能没有比这更进一步......对于包含文件1和2的命令的任何提示或建议?我确实需要包含文件1,因为实际上文件比这个例子大得多,但我想如果我知道如何用这个希望更简单的例子来解决其余的代码......很多提前谢谢!
答案 0 :(得分:9)
怎么样:
n=1
while read q
do
sed -e 's/ID/'${q}'/g' -e "s/NR/$n/" File_2.txt > Output_file_${n}.txt
((n++))
done < File_1.txt
请参阅Advanced Bash Scripting Guide on redirecting input to code blocks,或许the section on double parentheses进一步阅读。
答案 1 :(得分:3)
awk怎么样呢?
[ghoti@pc ~]$ cat file1
John
Mary
[ghoti@pc ~]$ cat file2
Harry
Bill
[ghoti@pc ~]$ cat merge.txt
My name is %s, and I am on the line %s of file '%s'.
[ghoti@pc ~]$ cat doit.awk
#!/usr/bin/awk -f
BEGIN {
while (getline line < "merge.txt") {
fmt = fmt line "\n";
}
}
{
file="Output_File_" NR ".txt";
printf(fmt, $1, FNR, FILENAME) > file;
}
[ghoti@pc ~]$ ./doit.awk file1 file2
[ghoti@pc ~]$ grep . Output_File*txt
Output_File_1.txt:My name is John, and I am on the line 1 of file 'file1'.
Output_File_2.txt:My name is Mary, and I am on the line 2 of file 'file1'.
Output_File_3.txt:My name is Harry, and I am on the line 1 of file 'file2'.
Output_File_4.txt:My name is Bill, and I am on the line 2 of file 'file2'.
[ghoti@pc ~]$
如果您真的希望对文件名进行编号,我们也可以这样做。
这里发生了什么?
awk脚本BEGIN通过读取merge.txt文件并逐行将其附加到变量“fmt”(由换行符分隔)。这使fmt
成为printf兼容格式字符串。
然后,对于输入文件中的每一行(在命令行中指定),选择一个输出文件(NR是跨越所有文件的当前记录计数)。 printf()函数用其中一个选项替换fmt变量中的每个%s
。输出被重定向到适当的文件。
grep
只会显示所有文件的内容及其文件名。
答案 2 :(得分:1)
这可能对您有用:
sed '=' File_1.txt |
sed '1{x;s/^/'"$(<File_2.txt)"'/;x};N;s/\n/ /;G;s/^\(\S*\) \(\S*\)\n\(.*\)ID\(.*\)NR\(.*\)/echo "\3\2\4\1\5" >Output_file_\1.txt/' |
bash
答案 3 :(得分:1)
TXR:
$ txr merge.txr
My name is John, and I am on the line 1 of file1.
My name is Mary, and I am on the line 2 of file1.
My name is Harry, and I am on the line 3 of file1.
My name is Bill, and I am on the line 4 of file1.
merge.txr:
@(bind count @(range 1))
@(load "file2.txt")
@(next "file1.txt")
@(collect)
@name
@(template name @(pop count) "file1")
@(end)
file2.txt:
@(define template (ID NR FILE))
@(output)
My name is @ID, and I am on the line @NR of @FILE.
@(end)
@(end)
答案 4 :(得分:1)
测试准备:
echo "John
Mary
Harry
Bill
" > names
姓名和号码:
name=($(<names))
max=$(($(echo ${#name[*]})-1))
for i in $(seq 0 $max) ; do echo $i":"${name[i]}; done
使用模板:
for i in $(seq 0 $max) ; do echo "My name is ID, and I am on the line NR of file 1." | sed "s/ID/${name[i]}/g;s/NR/$((i+1))/g"; done
My name is John, and I am on the line 1 of file 1.
My name is Mary, and I am on the line 2 of file 1.
My name is Harry, and I am on the line 3 of file 1.
My name is Bill, and I am on the line 4 of file 1.
答案 5 :(得分:1)
您的脚本需要稍加修改。请注意。
pearl.306> cat temp.sh
#!/bin/ksh
count=1
cat file1|while read line
do
sed -e "s/ID/${line}/g" -e "s/NR/${count}/g" File_2.txt > Output_file_${count}.txt
count=$(($count+1))
done
pearl.307>
pearl.303> temp.sh
pearl.304> ls -l Out*
-rw-rw-r-- 1 nobody nobody 59 Mar 29 18:54 Output_file_1.txt
-rw-rw-r-- 1 nobody nobody 58 Mar 29 18:54 Output_file_2.txt
-rw-rw-r-- 1 nobody nobody 58 Mar 29 18:54 Output_file_3.txt
-rw-rw-r-- 1 nobody nobody 58 Mar 29 18:54 Output_file_4.txt
-rw-rw-r-- 1 nobody nobody 58 Mar 29 18:54 Output_file_5.txt
pearl.305> cat Out*
My name is linenumber11, and I am on the line 1 of file 1.
My name is linenumber2, and I am on the line 2 of file 1.
My name is linenumber1, and I am on the line 3 of file 1.
My name is linenumber4, and I am on the line 4 of file 1.
My name is linenumber6, and I am on the line 5 of file 1.
pearl306>