如何按行号替换文本文件中的整行

时间:2012-06-21 19:20:44

标签: bash text replace sed

我有一种情况,我想要一个bash脚本来替换文件中的整行。 行号始终相同,因此可以是硬编码变量。

我不是要替换该行中的某些子字符串,我只想用新行替换该行。

是否有任何bash方法可以执行此操作(或者可以将其放入.sh脚本中的简单方法)。

9 个答案:

答案 0 :(得分:191)

不是最好的,但这应该有效:

sed -i 'Ns/.*/replacement-line/' file.txt

其中N应替换为您的目标行号。这将替换原始文件中的行。要将更改的文本保存在其他文件中,请删除-i选项:

sed 'Ns/.*/replacement-line/' file.txt > new_file.txt

答案 1 :(得分:42)

我实际上使用这个脚本来替换我们公司的UNIX服务器上的cron文件中的一行代码。我们将它作为普通的shell脚本执行并且没有问题:

#Create temporary file with new line in place
cat /dir/file | sed -e "s/the_original_line/the_new_line/" > /dir/temp_file
#Copy the new file over the original file
mv /dir/temp_file /dir/file

这不是按行号,但您可以通过将行号放在s/之前并放置通配符代替the_original_line,轻松切换到基于行号的系统。

答案 2 :(得分:17)

假设您要将第4行替换为“不同”的文本。您可以像这样使用AWK:

awk '{ if (NR == 4) print "different"; else print $0}' input_file.txt > output_file.txt

AWK认为输入是“记录”,分为“字段”。默认情况下,一行是一条记录。 NR是看到的记录数。 $0表示当前的完整记录(而$1是记录中的第一个字段,依此类推;默认情况下,字段是该行中的字词。)

因此,如果当前行号为4,则打印字符串“different”,否则打印行不变。

在AWK中,{ }中的程序代码在每个输入记录上运行一次。

您需要在单引号中引用AWK程序,以防止shell尝试解释$0之类的内容。

编辑:@chepner在以下评论中提供的更短,更优雅的AWK计划:

awk 'NR==4 {$0="different"} { print }' input_file.txt

仅对记录(即行号)4,用字符串“different”替换整个记录。然后,对于每个输入记录,打印记录。

显然我的AWK技能已经生锈了!谢谢@chepner。

编辑:还可以看一下@Dennis Williamson的更短版本:

awk 'NR==4 {$0="different"} 1' input_file.txt

注释中解释了它的工作原理:1始终计算为true,因此关联的代码块始终运行。但是没有相关的代码块,这意味着AWK只执行打印整行的默认操作。 AWK旨在允许像这样的简洁程序。

答案 3 :(得分:13)

鉴于此测试文件(test.txt)

Lorem ipsum dolor sit amet,
consectetur adipiscing elit. 
Duis eu diam non tortor laoreet 
bibendum vitae et tellus.

以下命令将第一行替换为“换行文本”

$ sed '1 c\
> newline text' test.txt

结果:

newline text
consectetur adipiscing elit. 
Duis eu diam non tortor laoreet 
bibendum vitae et tellus.

可在此处找到更多信息

http://www.thegeekstuff.com/2009/11/unix-sed-tutorial-append-insert-replace-and-count-file-lines/

答案 4 :(得分:7)

在bash中,用行号替换N,M,用你想要的xxx yyy替换

i=1
while read line;do
  if((i==N));then
    echo 'xxx'
  elif((i==M));then
    echo 'yyy'
  else
    echo "$line"
  fi
  ((i++))
done  < orig-file > new-file

修改

事实上在这个解决方案中存在一些问题,字符为“\ 0”“\ t”和“\”

“\ t”,可以通过在读取之前放入IFS =来解决: “\”,在-r

行的末尾
IFS= read -r line

但对于“\ 0”,变量被截断,纯bash中没有解决方案: Assign string containing null-character (\0) to a variable in Bash 但在普通文本文件中没有空字符\ 0

perl将是一个更好的选择

perl -ne 'if($.==N){print"xxx\n"}elsif($.==M){print"yyy\n"}else{print}' < orig-file > new-file

答案 5 :(得分:2)

切普纳的优秀答案。 它在bash Shell中为我工作。

 # To update/replace the new line string value with the exiting line of the file
 MyFile=/tmp/ps_checkdb.flag

 `sed -i "${index}s/.*/${newLine}/" $MyFile`

这里         index - 行号         newLine - 我们要替换的新行字符串。


类似地,下面的代码用于读取文件中的特定行。这不会影响实际文件。

LineString=`sed "$index!d" $MyFile` 

这里         !d - 将删除第$index行以外的行         因此,我们将输出作为文件中没有$index的行字符串。

答案 6 :(得分:2)

# Replace the line of the given line number with the given replacement in the given file.
function replace-line-in-file() {
    local file="$1"
    local line_num="$2"
    local replacement="$3"

    # Escape backslash, forward slash and ampersand for use as a sed replacement.
    replacement_escaped=$( echo "$replacement" | sed -e 's/[\/&]/\\&/g' )

    sed -i "${line_num}s/.*/$replacement_escaped/" "$file"
}

答案 7 :(得分:0)

在我使用过的Mac上

sed -i '' -e 's/text-on-line-to-be-changed.*/text-to-replace-the=whole-line/' file-name

答案 8 :(得分:-2)

您甚至可以将参数传递给sed命令:

<强> test.sh

#!/bin/bash
echo "-> start"
for i in $(seq 5); do
  # passing parameters to sed
  j=$(($i+3))
  sed -i "${j}s/.*/replaced by '$i'!/" output.dat
done
echo "-> finished"
exit 

orignial output.dat:

a
b
c
d
e
f
g
h
i
j

执行 ./ test.sh 会给出新的output.dat

a
b
c
replaced by '1'!
replaced by '2'!
replaced by '3'!
replaced by '4'!
replaced by '5'!
i
j