使用Shell脚本在指定模式后将多行插入文件


75

我想使用Shell脚本在文件中插入多行。让我们考虑一下我的输入文件内容是: input.txt:

abcd
accd
cdef
line
web

现在,我必须在input.txt文件中的'cdef'行之后插入四行。插入我的文件后,应更改为:

abcd
accd
cdef
line1
line2
line3
line4
line
web

上面的插入我应该使用shell脚本来做。谁能帮我?

Answers:


98

另一个sed

sed '/cdef/r add.txt' input.txt

input.txt:

abcd
accd
cdef
line
web

add.txt:

line1
line2
line3
line4

测试:

sat:~# sed '/cdef/r add.txt' input.txt
abcd
accd
cdef
line1
line2
line3
line4
line
web

如果要应用input.txt文件中的更改。然后,-i与一起使用sed

sed -i '/cdef/r add.txt' input.txt

如果要将正则表达式用作表达式,则必须将-E标记与一起使用sed

sed -E '/RegexPattern/r add.txt' input.txt

是否有其他方法可以做到这一点(从input.txt中删除add.txt中找到的文本)?
新浪

2
允许匿名文件的一种变体是将Here文档传送到sed调用中,并使用r命令从中读取/dev/stdin
potong

嗨,有没有一种快速的方法可以在的添加行之前添加4个空格add.txt
哈德

36

使用GNU sed

sed "/cdef/aline1\nline2\nline3\nline4" input.txt

如果您开始使用:

abcd
accd
cdef
line
web

这将产生:

abcd
accd
cdef
line1
line2
line3
line4
line
web

如果要就地保存对文件的更改,请说:

sed -i "/cdef/aline1\nline2\nline3\nline4" input.txt

4
我是新手,sed但哇,我爱上它的力量!如果你想添加一个空的换行首先你要逃避这样的附加命令后反斜杠字符:sed "/cdef/a\\\nline1\nline2\nline3\nline4" input.txt。我不确定为什么它会那样工作,如果有人可以解释的话,那会很好!
hdl 2015年

1
当前命令在每次提及时都插入line * cdef,是否有办法使其仅在第一次遇到时才插入cdef
CMCDragonkai

1
MacOS的sed不执行a命令完全相同的GNU sed,所以在MacOS上没有MODS以上将无法正常工作-至少10.13的MacOS(见unix.stackexchange.com/a/131940/230763
迈克·鲁茨

24
sed '/^cdef$/r'<(
    echo "line1"
    echo "line2"
    echo "line3"
    echo "line4"
) -i -- input.txt

错过了这个好答案。较短,但可读性较差sed '/^cdef$/r' <(printf "%s\n" line{1..4}) -i -- input.txt
Walter A

16

使用awk

awk '/cdef/{print $0 RS "line1" RS "line2" RS "line3" RS "line4";next}1' input.txt 

说明:

  • 您发现要使用插入的行 /.../
  • 您使用以下命令打印当前行 print $0
  • RS是内置awk变量,默认情况下设置为new-line
  • 您添加由该变量分隔的新行
  • 1最后导致每隔一行打印一次。next在它之前使用允许我们阻止当前行,因为您已经使用进行了打印print $0

$ awk '/cdef/{print $0 RS "line1" RS "line2" RS "line3" RS "line4";next}1' input.txt
abcd
accd
cdef
line1
line2
line3
line4
line
web

要更改文件,您可以执行以下操作:

awk '...' input.txt > tmp && mv tmp input.txt

1

这个答案很容易理解

  • 在图案之前复制
  • 添加行
  • 图案后复制
  • 替换原始文件

    FILENAME ='app / Providers / AuthServiceProvider.php'

步骤1复制直到图案

sed '/THEPATTERNYOUARELOOKINGFOR/Q' $FILENAME >>${FILENAME}_temp

步骤2添加您的行

cat << 'EOL' >> ${FILENAME}_temp

HERE YOU COPY AND
PASTE MULTIPLE
LINES, ALSO YOU CAN
//WRITE COMMENTS

AND NEW LINES
AND SPECIAL CHARS LIKE $THISONE

EOL

STEP 3添加其余文件

grep -A 9999 'THEPATTERNYOUARELOOKINGFOR' $FILENAME >>${FILENAME}_temp

替换原始文件

mv ${FILENAME}_temp $FILENAME

如果需要变量,请在步骤2中将“ EOL”替换为EOL

cat << EOL >> ${FILENAME}_temp

this variable will expand: $variable1

EOL

1

这是基于@rindeal解决方案的更通用的解决方案,该解决方案 在MacOS / BSD上不起作用(/r需要文件):

cat << DOC > input.txt
abc
cdef
line
DOC
$ cat << EOF | sed '/^cdef$/ r /dev/stdin' input.txt
line 1
line 2
EOF

# outputs:
abc
cdef
line 1
line 2
line

这可以用于将任何内容通过管道传递到文件中的指定位置:

$ date | sed '/^cdef$/ r /dev/stdin' input.txt

# outputs
abc
cdef
Tue Mar 17 10:50:15 CET 2020
line

此外,您可以添加多个命令,以删除标记行cdef

$ date | sed '/^cdef$/ {
  r /dev/stdin
  d
}' input.txt

# outputs
abc
Tue Mar 17 10:53:53 CET 2020
line

0

我需要用最少的工具来模板化几个文件,对我来说,上面的问题sed -e '/../r file.txt是它仅在打印出其余匹配项后才追加文件,而不是替换它。

这样做不会(替换所有匹配项,并且模式匹配从同一点继续)

#!/bin/bash

TEMPDIR=$(mktemp -d "${TMPDIR:-/tmp/}$(basename $0).XXXXXXXXXXXX")
# remove on exit
trap "rm -rf $TEMPDIR" EXIT

DCTEMPLATE=$TEMPDIR/dctemplate.txt
DCTEMPFILE=$TEMPDIR/dctempfile.txt

# template that will replace
printf "0replacement
1${SHELL} data
2anotherlinenoEOL" > $DCTEMPLATE

# test data
echo -e "xxy \n987 \nxx xx\n yz yxxyy" > $DCTEMPFILE

# print original for debug
echo "---8<--- $DCTEMPFILE"
cat $DCTEMPFILE
echo "---8<--- $DCTEMPLATE"
cat $DCTEMPLATE
echo "---8<---"

# replace 'xx' -> contents of $DCTEMPFILE
perl -e "our \$fname = '${DCTEMPLATE}';" -pe 's/xx/`cat $fname`/eg' ${DCTEMPFILE}

0

您可以awk用于在中间插入某些命令的输出input.txt
要被插入的线可以是a的输出cat otherfilels -l或与由生成的数字4行printf

awk 'NR==FNR {a[NR]=$0;next}
    {print}
    /cdef/ {for (i=1; i <= length(a); i++) { print a[i] }}'
    <(printf "%s\n" line{1..4}) input.txt

0

如果您想使用bash脚本执行此操作,则很有用。

echo $password | echo 'net.ipv4.ping_group_range=0 2147483647' |  sudo -S tee -a /etc/sysctl.conf

您可以在命令中添加一些解释,以帮助将来的读者了解已做的事情吗?
鲁里
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.