使用sed或awk在特定行号处插入一行

使用sed或awk在特定行号处插入一行,sed,awk,Sed,Awk,我有一个脚本文件,我需要用另一个脚本修改它,以便在第8行插入文本 要插入的字符串:Project\u Name=sowstest,插入名为start的文件中 我试图使用awk和sed,但我的命令变得混乱 sed -i '8i8 This is Line 8' FILE 在第8行插入 8 This is Line 8 归档 -i直接对文件进行修改,不输出到标准输出,正如glenn jackman在评论中提到的那样 awk答案 awk -v n=8 -v s="Project_Name=sows

我有一个脚本文件,我需要用另一个脚本修改它,以便在第8行插入文本

要插入的字符串:
Project\u Name=sowstest
,插入名为
start
的文件中

我试图使用awk和sed,但我的命令变得混乱

sed -i '8i8 This is Line 8' FILE
在第8行插入

8 This is Line 8
归档

-i
直接对文件进行修改,不输出到标准输出,正如glenn jackman在评论中提到的那样

awk答案

awk -v n=8 -v s="Project_Name=sowstest" 'NR == n {print s} {print}' file > file.new

ed
答案

ed file << END
8i
Project_Name=sowstest
.
w
q
END

ed file对于那些使用非GNU的SunOS的用户,以下代码将有所帮助:

sed '1i\^J
line to add' test.dat > tmp.dat
  • ^J与^V+^J一起插入
  • 在“1i”之后添加换行符
  • \必须是行的最后一个字符
  • 命令的第二部分必须在第二行中
POSIX
sed
(例如OSX的
sed
,下面的
sed
)要求
i
后跟反斜杠和换行符。此外,至少OS X的
sed
在插入的文本后不包含换行符:

$ seq 3|gsed '2i1.5'
1
1.5
2
3
$ seq 3|sed '2i1.5'
sed: 1: "2i1.5": command i expects \ followed by text
$ seq 3|sed $'2i\\\n1.5'
1
1.52
3
$ seq 3|sed $'2i\\\n1.5\n'
1
1.5
2
3
要替换行,可以使用带有数字地址的
c
(更改)或
s
(替换)命令:

$ seq 3|sed $'2c\\\n1.5\n'
1
1.5
3
$ seq 3|gsed '2c1.5'
1
1.5
3
$ seq 3|sed '2s/.*/1.5/'
1
1.5
3
使用awk的备选方案

$ seq 3|awk 'NR==2{print 1.5}1'
1
1.5
2
3
$ seq 3|awk '{print NR==2?1.5:$0}'
1
1.5
3
awk
解释使用
-v
传递的变量中的反斜杠,但不解释使用
环境传递的变量中的反斜杠:

$ seq 3|awk -v v='a\ba' '{print NR==2?v:$0}'
1
a
3
$ seq 3|v='a\ba' awk '{print NR==2?ENVIRON["v"]:$0}'
1
a\ba
3
ENVIRON
-v
都是由POSIX定义的。

Perl解决方案:

又快又脏:
perl-lpe'如果$==8'文件

  • -l
    剥离新行并将其添加回,从而消除了对“\n”的需要
  • -p
    在输入文件上循环,打印每一行
  • -e
    以单引号执行代码
$。
是行号

等效于@glenn的awk解决方案,使用命名参数:
perl-slpe'print$s if$。==$n'--n=8-s=“Project\u Name=sowstest”文件

  • -s
    启用基本参数解析器
  • --
    防止标准perl参数解析器解析-n和-s
位置命令参数:
perl-lpe'BEGIN{$n=shift;$s=shift};如果$=,则打印$s$n'8“项目名称=sowstest”文件

环境变量:
ENV
是包含所有环境变量的哈希

Getopt将参数解析为哈希%o:
perl-MGetopt::Std-lpe'BEGIN{getopt(“ns”,\%o)};如果$==打印$o{s}$o{n}'-n8-s“Project_Name=sowstest”文件

Getopt::长的和更长的选项名称
perl-MGetopt::Long-lpe'BEGIN{GetOptions(\%o,“line=i”,“string=s”);如果$.==打印$o{string}$o{line}'--第8行--字符串“Project_Name=sowstest”文件

Getopt是推荐的标准库解决方案。
对于一行perl脚本来说,这可能有点过头了,但是可以做到

OSX/macOS/FreeBSD
sed
-i
标志在macOS
sed
上的工作方式与GNU
sed
上的工作方式不同

以下是在macOS/OS X上使用它的方法:

sed -i '' '8i\
8 This is Line 8' FILE

有关更多信息,请参见。

sed-e'8iProject\u Name=sowstest'-i使用GNU-sed启动

样本运行:

[root@node23 ~]# for ((i=1; i<=10; i++)); do echo "Line #$i"; done > a_file
[root@node23 ~]# cat a_file
Line #1
Line #2
Line #3
Line #4
Line #5
Line #6
Line #7
Line #8
Line #9
Line #10
[root@node23 ~]# sed -e '3ixxx inserted line xxx' -i a_file 
[root@node23 ~]# cat -An a_file 
     1  Line #1$
     2  Line #2$
     3  xxx inserted line xxx$
     4  Line #3$
     5  Line #4$
     6  Line #5$
     7  Line #6$
     8  Line #7$
     9  Line #8$
    10  Line #9$
    11  Line #10$
[root@node23 ~]# 
[root@node23 ~]# sed -e '5ixxx (inserted) "line" xxx' -i a_file
[root@node23 ~]# cat -n a_file 
     1  Line #1
     2  Line #2
     3  xxx inserted line xxx
     4  Line #3
     5  xxx (inserted) "line" xxx
     6  Line #4
     7  Line #5
     8  Line #6
     9  Line #7
    10  Line #8
    11  Line #9
    12  Line #10
[root@node23 ~]# 
[root@node23~]#for((i=1;i)是一个文件
[root@node23~]#cat a#U文件
第1行
第2行
第3行
第4行
第5行
第6行
第7行
第8行
第9行
第10行
[root@node23~]#sed-e'3ixxx插入行xxx'-i a#u文件
[root@node23~]#cat-一个a#u文件
1行#1$
2行#2$
3 xxx插入行xxx$
4行#3$
5行#4$
6行#5$
7行#6$
8行#7$
9行#8$
10行#9$
11行#10$
[root@node23 ~]# 
[root@node23~]#sed-e'5ixxx(插入)“行”xxx'-i a_文件
[root@node23~]#cat-n a_文件
1行#1
2行#2
3 xxx插入行xxx
4行#3
5 xxx(插入)“行”xxx
6行#4
7行#5
8行#6
9行#7
10行#8
11行#9
12行#10
[root@node23 ~]# 
sed-i'-e$'4 a\\n''Project\u Name=sowstest'启动

  • 这条线在macOS中运行良好

是的,-i开关特定于GNU-sed。否。-我的意思是“就地修改指定的文件”插入与追加是通过“8isomething”与“8asomething”实现的,独立于-i-switch.mac用户:使用自制,
brew安装gnu sed
,然后与
gsed
一起使用,这非常有用!我是否可以在行的开头插入空格?我注意到sed没有注意初始空格ace…@elju:是的,用反斜杠遮住它:
sed'8i\8这是第8行”文件
@glenn jackman我需要输入
#定义服务器@”http://10.35.42.54/ms0.8"
到某一行。我怎么能做到这一点呢?我想内文只需要用backslashes@waLLe,从它开始,它很好地描述了awk是如何工作的配对,第二个没有条件,这意味着对每条记录都执行操作。读完后,如果还有问题,请告诉我。@glennjackman就快到了。。只是没有得到这个:file>file.new“file”表示awk正在处理的文件的名称。
是shell符号,因此awk的输出存储在名为“file.new”的文件中.Chris,感谢你花时间解释了这一切,并把它布置得如此漂亮,但哇,这就是我不喜欢perl的原因。插入后第3行的尾随
$
来自哪里?它来自
-A
标志到
cat
:)如果要插入的字符串包含引号、括号等,该怎么办?请参阅上面的文本更新。这意味着您必须根据需要转义这些字符。是否可以使用变量而不是字符串文本内联来执行此操作?@AndyRay使用double
[root@node23 ~]# for ((i=1; i<=10; i++)); do echo "Line #$i"; done > a_file
[root@node23 ~]# cat a_file
Line #1
Line #2
Line #3
Line #4
Line #5
Line #6
Line #7
Line #8
Line #9
Line #10
[root@node23 ~]# sed -e '3ixxx inserted line xxx' -i a_file 
[root@node23 ~]# cat -An a_file 
     1  Line #1$
     2  Line #2$
     3  xxx inserted line xxx$
     4  Line #3$
     5  Line #4$
     6  Line #5$
     7  Line #6$
     8  Line #7$
     9  Line #8$
    10  Line #9$
    11  Line #10$
[root@node23 ~]# 
[root@node23 ~]# sed -e '5ixxx (inserted) "line" xxx' -i a_file
[root@node23 ~]# cat -n a_file 
     1  Line #1
     2  Line #2
     3  xxx inserted line xxx
     4  Line #3
     5  xxx (inserted) "line" xxx
     6  Line #4
     7  Line #5
     8  Line #6
     9  Line #7
    10  Line #8
    11  Line #9
    12  Line #10
[root@node23 ~]#