繁体   English   中英

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

[英]Insert multiple lines into a file after specified pattern using shell script

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

abcd
accd
cdef
line
web

现在我必须在input.txt文件中的“cdef”行之后插入四行。 插入我的文件后应该像这样改变:

abcd
accd
cdef
line1
line2
line3
line4
line
web

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

另一个sed

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

输入.txt:

abcd
accd
cdef
line
web

添加.txt:

line1
line2
line3
line4

测试:

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

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

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

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

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

使用 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
sed '/^cdef$/r'<(
    echo "line1"
    echo "line2"
    echo "line3"
    echo "line4"
) -i -- input.txt

使用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

这是一个基于 @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

这个答案很容易理解

  • 在模式之前复制
  • 添加您的线路
  • 在模式后复制
  • 替换原文件

    FILENAME='app/Providers/AuthServiceProvider.php'

STEP 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

我需要用最少的工具来模板化一些文件,对我来说,上面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}

您可以使用awkinput.txt中间插入某些命令的输出。
要插入的行可以是cat otherfilels -l或带有printf生成的数字的 4 行的输出。

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

如果你想用 bash 脚本来做到这一点,那很有用。

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

假设您有一个名为“insert.txt”的文件,其中包含要添加的行:

line1
line2
line3
line4

如果模式 'cdef' 在 input.txt 文件中重复多次,并且您想在所有出现的模式 'cdef' 之后添加来自 'insert.txt' 的行,那么一个简单的解决方案是:

sed -i -e '/cdef/r insert.txt' input.txt

但是,如果您的 input.txt 文件中的 PATTERN 'cdef' 重复多次,并且您只想在该模式第一次出现后添加来自 'insert.txt' 的行,那么一个漂亮的解决方案是:

printf "%s\\n" "/cdef/r insert.txt" w | ed -s input.txt

如果该模式仅在 input.txt 文件中出现一次,则这两种解决方案都可以正常工作。

基于@rindeal解决方案,但具有更好的输入可读性

sed '/^cdef$/r'<(cat <<EOF
line1
line2
line3
line4
EOF
) -i -- input.txt

将内容放在第 4 行(如你所愿)

sed -i "4i line1\nline2\nline3\nline4" input.txt

如果您不想就地保存对文件的更改,请删除“-i”:

sed "4i line1\nline2\nline3\nline4" input.txt

GNU* 使用 sed

如果您使用以下命令启动 input.txt:

abcd
accd
cdef
line
web

这会产生:

abcd
accd
cdef
line1
line2
line3
line4
line
web

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM