183

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

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

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

4

11 回答 11

277

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

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

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

sed 'Ns/.*/replacement-line/' file.txt > new_file.txt
于 2012-06-21T19:26:37.013 回答
45

不久前,我实际上使用此脚本替换了我们公司 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

于 2012-06-21T19:32:24.753 回答
26

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

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

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

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

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

您需要在单引号中引用 AWK 程序,以防止 shell 尝试解释$0.

编辑:@chepner 在下面的评论中提供了一个更短、更优雅的 AWK 程序:

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

仅对于第 4 条记录(即行),将整个记录替换为字符串“不同”。然后对于每个输入记录,打印记录。

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

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

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

注释中解释了它是如何工作的:1总是评估为真,因此相关的代码块总是运行。但是没有关联的代码块,这意味着 AWK 执行其仅打印整行的默认操作。AWK 旨在允许这样的简洁程序。

于 2012-06-21T19:27:12.750 回答
20

给定这个测试文件(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/

于 2012-06-21T19:30:30.897 回答
8

在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 中没有解决方案: 将包含空字符 (\0) 的字符串分配给 Bash 中的变量 但是在普通文本文件中没有空字符 \0

perl 会是更好的选择

perl -ne 'if($.==N){print"xxx\n"}elsif($.==M){print"yyy\n"}else{print}' < orig-file > new-file
于 2012-06-21T19:29:21.990 回答
7
# 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"
}
于 2017-03-10T21:20:52.967 回答
3

Chepner的出色回答。它在 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- 将删除除第 no 行以外的行$index 所以我们将输出作为$index文件中 no 的行字符串。

于 2014-04-24T12:36:21.153 回答
3

在我使用的mac上

sed -i '' -e 's/text-on-line-to-be-changed.*/text-to-replace-the=whole-line/' file-name
于 2018-12-05T18:46:24.137 回答
1

将行替换为sed c\

参考

sed c\实际上不会更改文件,因此您需要将其输出发送到临时文件,然后cat将临时文件发送到原始文件。匹配模式不是必需的,因为我们可以指定行。示例:sed '1 c\'=> 将替换第 1 行中的文本。

编写命令时,该c\部分之后的任何内容都将换行并应包含新行文本。


最后,示例“替换”以original_file.txt文本“foo”命名的文件中的第 1 行。请注意,我们正在获取 sed 输出并保存在临时文件中,然后将临时文件输出回原始文件:

# file contents
$ cat original_file.txt
bar

# the replace command
$ sed '1 c\
  foo' original_file.txt > temp_file.txt
 
# output contents of temp_file and overwrite original
$ cat temp_file.txt > original_file.txt

# delete the temp file
$ rm -rf temp_file.txt
于 2021-12-13T23:36:58.717 回答
0

如果您想为 lineNumber 和 replacementLine 使用参数,那么 awk 就不能轻松工作(对我来说)。我在 1 小时后运行,您可以在下面看到 :)

lineNumber=$(grep --line-number "u want to replace line any keyword" values.txt  | cut -f1 -d:)
replacedLine="replacing new Line "
# for sed prepare => if your replacedLine have '/' character (URL or something) u must use command bellow. 
replacedLine=${replacedLine//\//\\\/}

sed -i $lineNumber's/.*/'"$replacedLine"'/'  values.txt
于 2022-01-06T09:20:14.653 回答
-2

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

测试.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 

原始输出.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
于 2017-12-08T08:14:36.360 回答