我正在尝试根据另一个文件的内容替换文件中的现有标头。
文件 1 - 名称.in:
name1
name2
name3
name4
name5
文件2-数据文件.tsv:
chr begin end genes genes genes genes genes
File2
包含更多行,但我想将第一行中出现的每个字符串替换genes
为 中的连续条目file1
,以便标题变为:
chr begin end name1.Corrected name2.Corrected name3.Corrected name4.Corrected name5.Corrected
我尝试了以下脚本:
genenames=$1
sed -i -e "1s/\tgenes/\t$genenames\.Corrected/g" Datafile.tsv
但是当我像这样运行它时:
./sed.sh names.in
我得到的输出为:
chr begin end .in.Corrected .in.Corrected .in.Corrected .in.Corrected .in.Corrected
我可以理解该脚本不会从输入中读取。
答案1
尝试
for x in $(<names.in)
do
sed -i -s "s/ genes/ ${x}.Corrected/" Datafile.tsv
done
cat Datafile.tsv
chr begin end name1.Corrected name2.Corrected name3.Corrected name4.Corrected name5.Corrected
- 不要使用
/g
适用于所有事件的标志(您想一一替换) 替换我
' '
的'\t'
$names.in
将扩展为“名称变量的值”(连接到 .in),这可能会扩展为 .in$(< name.in )
在命令执行之前读取文件 name.in 并替换为文件内容(行尾变为白色)
更全面的外壳
cat "$1" | while read x
do
sed -i -s "s/ genes/ ${x}.Corrected/" "$2"
done
称为
myscript.sh names.in Datafile.tsv
答案2
如果我理解正确,您需要读取名称file1
并将每个出现的字符串替换genes
为 file1 中的连续条目,但仅限于 file2 的第一行。如果是这样,你可以这样做(假设你从来没有一个字符串genes
作为子字符串,例如mygenes
):
while read name
do
sed -i "1s/genes/$name.Corrected/" file2
done < file1
或者,您也可以简单地连接 file1 的内容并一次性替换所有内容:
names=$(perl -pe 's/\n/.Corrected /' file1)
sed -i "1s/genes .*/$names/" file2
答案3
没有什么比处理文本时的循环while read
,但以防万一您想处理您的datafile.tsv
只有一次:
sed 's|\(.*\)|1s/genes/\1.Corrected/|' names.in | sed -f - datafile.tsv
第一个sed
变成names.in
了sed脚本:
1s/genes/name1.Corrected/
1s/genes/name2.Corrected/
1s/genes/name3.Corrected/
1s/genes/name4.Corrected/
1s/genes/name5.Corrected/
然后由第二个执行sed
。
如果你所有的基因列是连续的(就像在示例输入中一样),您也可以运行:
tr \\n \\t <names.in | \
sed -E 's|\t|.Corrected&|g;s|(.*).$|1s/genes.*genes/\1/|' | \
sed -f - datafile.tsv
这与第一个类似,因为最后一个sed
执行以下内容sed脚本:
1s/genes.*genes/name1.Corrected name2.Corrected name3.Corrected name4.Corrected name5.Corrected/
请注意,这些不会就地编辑您的文件。为此,请使用sed
with -i
(如果支持)或将>
输出重定向到例如newfile
thenmv newfile datafile.tsv