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

use*_*171 137 bash text replace sed

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

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

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

che*_*ner 201

不是最好的,但这应该工作:

sed -i 'Ns/.*/replacement-line/' file.txt
Run Code Online (Sandbox Code Playgroud)

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

sed 'Ns/.*/replacement-line/' file.txt > new_file.txt
Run Code Online (Sandbox Code Playgroud)

  • 对我来说它说:`sed:-e表达式#1,字符26:对``s'的未知选项,我的行是:`sed -i'7s /.*/ <param-value> http:// localhost :8080/ASDF/services/REWS.REWSHttpSoap12Endpoint/</ param-value> /'$ TCE_SVN_HOME\trunk\tce\EWC\WebContent\WEB-INF\web.xml`.任何的想法? (7认同)
  • 要扩展@ meonlol,如果给出`-i`,macOS需要`-e`; 因此,正确的命令变为:`sed -e'Ns /.*/ replacement-line /'- i''file.txt` (5认同)
  • 如果替换行不固定,请使用**双引号**,例如它是一个变量,像这样:`sed -i "Ns/.*/foo=$myVar" file.txt`。 (4认同)
  • 除非转义(`\ /`),否则替换文本中的每个`/`都将被解释为`s`命令的结束斜杠.但是,最简单的方法是选择一个不同的,未使用的字符作为分隔符.例如,`sed -i'7s {.*} {<param-value> http:// ...}'$ TCE_SVN_HOME/trunk ...`. (3认同)
  • 这种解释有点混乱,似乎不起作用.如果你们有sed及其分隔符设置功能的问题,你可能想看看这个:http://www.grymoire.com/Unix/Sed.html#uh-2它说的是`s后面的第一个字符`确定分隔符.所以要改变你的命令使用例如```它就像这样:`sed -i'7s#.*#<param-value> http:// localhost:8080/ASDF/services/REWS.REWSHttpSoap12Endpo INT/</ PARAM值>#'` (3认同)

Kyl*_*yle 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
Run Code Online (Sandbox Code Playgroud)

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

  • 解释器/编译器可能没用,但不适合人类阅读它.@Kyle的代码从左到右读得很好; 由于动词在名词之前的事实,你使用IMO的习语不会. (21认同)
  • 无用的cat:`sed -e"s /.../.../"/ dir/file>/dir/temp_file` (15认同)
  • @PubeduDodangoda sed -i 会实现这一点 (2认同)

ste*_*eha 19

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

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

AWK认为输入是"记录",分为"字段".默认情况下,一行是一条记录. NR是看到的记录数. $0表示当前的完整记录(同时$1是记录中的第一个字段,依此类推;默认情况下,字段是来自行的单词).

因此,如果当前行号为4,则打印字符串"不同",否则打印行不变.

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

你需要用单引号引用AWK程序,以防止shell试图解释像$0.

编辑:来自@chepner的更简短,更优雅的AWK程序,在下面的评论中:

awk 'NR==4 {$0="different"} { print }' input_file.txt
Run Code Online (Sandbox Code Playgroud)

仅对于记录(即行)编号4,将整个记录替换为字符串"different".然后,对于每个输入记录,打印记录.

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

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

awk 'NR==4 {$0="different"} 1' input_file.txt
Run Code Online (Sandbox Code Playgroud)

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

  • 稍微短一些:`awk'NR == 4 {$ 0 ="different"} {print}'input_file.txt`. (3认同)
  • @chepner:更短一些:`awk'NR == 4 {$ 0 ="different"} 1'input_file.txt` (2认同)
  • 我想有一种方法可以缩写无条件打印!@stevaha:1只是一个真值,意味着一个始终匹配的“模式”。匹配的默认操作是打印当前行。 (2认同)

Eri*_*son 16

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

Lorem ipsum dolor sit amet,
consectetur adipiscing elit. 
Duis eu diam non tortor laoreet 
bibendum vitae et tellus.
Run Code Online (Sandbox Code Playgroud)

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

$ sed '1 c\
> newline text' test.txt
Run Code Online (Sandbox Code Playgroud)

结果:

newline text
consectetur adipiscing elit. 
Duis eu diam non tortor laoreet 
bibendum vitae et tellus.
Run Code Online (Sandbox Code Playgroud)

更多信息可以在这里找到

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

  • 这是正确的答案,但为什么会有丑陋的换行符呢?`sed '1 cnewline text' test.txt` 也可以做到这一点。 (6认同)
  • 这应该是正确的答案.c标志完全符合要求(用给定文本替换带编号的行). (2认同)

Nah*_*eul 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
Run Code Online (Sandbox Code Playgroud)

编辑

实际上在这个解决方案中有一些问题,字符"\ 0""\ t"和"\"

"\ t",可以通过在读取之前放置IFS =来解决:"\",在带有-r的行尾

IFS= read -r line
Run Code Online (Sandbox Code Playgroud)

但是对于"\ 0",变量被截断,纯bash中没有解决方案: 将包含空字符(\ 0)的字符串分配给Bash中的变量 但是在普通文本文件中没有空字符\ 0

perl将是一个更好的选择

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


Dan*_*ham 6

# 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"
}
Run Code Online (Sandbox Code Playgroud)