[英]Using Regex to replace or append line in file | Linux Shell script
我试图在一个看起来像这样的文件上找到正确的命令来执行:(即.cshrc文件)
setenv BLAH foo
我需要命令来替换检测到字符串BLAH
并替换整行,如下所示:
setenv BLAH newfoo
如果文件中不存在BLAH
,则将其附加到文件中。
我已经玩过这样的sed
,但这并没有实现我的目标。
sed 's/^.*?BLAH.*/setenv BLAH newfoo/g' text.txt > text.tmp && mv text.tmp text.txt
我也玩过awk
并且似乎无法使命令正常工作我想要它。
awk -v s="setenv BLAH newfoo" '/^BLAH/{f=1;$0=s}7;END{if(!f)print s}' text.txt > text.tmp && mv text.tmp text.txt
关于如何实现这一点的任何想法都会很棒。
我试图让这个脚本按预期工作。
ARG1="$1"
sed -i "/BLAH/s/^.*\$/setenv ${ENV_KEY} ${ENV_VAL}/g" file.txt
# If the BLAH keyword isnt there, append the file then.
grep -v -q "BLAH" file.txt && echo "setenv BLAH ${ARG1}" >> file.txt
setenv BLAH randomstring
script.sh newvalue
setenv BLAH newvalue
目前,脚本似乎每次都附加文件。 我还尝试了一些其他的建议,但我不能让他们接受sed字符串中的传入arg1值。
这可以通过这个sed脚本完成:
sed '/BLAH/{s/ \w+$/ newfoo/;h};${x;/BLAH/ba;x;s/$/\nsetenv BLAH newfoo/;x;:a;x}'
sed -e '
/^\(\|.*\W\)BLAH\(\W.*\|\)$/{ # lines matching word BLAH
s/ \w\+$/ newfoo/; # replace last word by "newfoo"
h; # Store for not adding them at end of file
};
${ # On last line...
x; # Swap stored line with current line
/BLAH/ba; # if match, branch to label a:
x; # Swap back
s/$/\nsetenv BLAH newfoo/; # Replace end of line with newline...
x; # Swap again
:a; # Label a:
x # Swap back
}'
您可以使用就地编辑开关:
sed -e'/BLAH/{h};${x;/BLAH/ba;x;s/$/\nsetenv BLAH newfoo/;x;:a;x}' -i text.txt
为了更准确,搜索分隔的单词BLAH
:
sed -e '
/^\(.*\W\|\)BLAH\(\W.*\|\)$/{h}; # Store lines matching word BLAH
${ # On last line...
x; # Swap stored line with current line
/./ba; # if match, branch to label a:
x; # Swap back
s/$/\nsetenv BLAH newfoo/; # Replace end of line with newline...
x; # Swap again
:a; # Label a:
x # Swap back
}' <(echo BLAH=foo;seq 1 4)
BLAH=foo
1
2
3
4
而
sed -e '
/^\(.*\W\|\)BLAH\(\W.*\|\)$/{h}; # Store lines matching word BLAH
${ # On last line...
x; # Swap stored line with current line
/./ba; # if match, branch to label a:
x; # Swap back
s/$/\nsetenv BLAH newfoo/; # Replace end of line with newline...
x; # Swap again
:a; # Label a:
x # Swap back
}' <(echo BLAHBLAH=foo;seq 1 4)
BLAHBLAH=foo
1
2
3
4
setenv BLAH newfoo
您可能会看到第二个BLAH
被替换为.
。 这可以完成,因为如果找不到1st,则交换空间为空。 因此,如果至少有一个字符,这意味着第一个确实发生了。
有一种方法可以使它更具脚本化 :
sedcmd='/^\(.*\W\|\)%s\(\W.*\|\)$/{s/ \w\+$/ %s/;h};'
sedcmd+='${x;/./ba;x;s/$/\\nsetenv %s %s/;x;:a;x}'
varnam=BLAH
varcnt=foo
filnam=/tmp/file.txt
printf -v sedcmd "$sedcmd" ${varnam} ${varcnt} ${varnam} ${varcnt}
sed -e "$sedcmd" -i "$filnam"
你可以删除最后一行的-i
开关......
您可以通过运行来尝试:
sed -e "$sedcmd" <(echo setenv BLAH oldfoo;seq 1 4)
setenv BLAH foo
1
2
3
4
sed -e "$sedcmd" <(echo setenv BLAHBLAH oldfoo;seq 1 4)
setenv BLAHBLAH oldfoo
1
2
3
4
setenv BLAH foo
这个awk
命令应该适用于两种情况:
awk -v kw='BLAH' '$2 == kw{$3="newfoo"; seen=1} 1;
END{if (!seen) print "setenv " kw " newfoo"}' file
您可以使用-v kw=...
命令行选项将ny其他关键字传递给搜索。
只有在文件中找不到给定的关键字时, END
块才会执行。
我认为你可以使sed
更容易,如果你之后用快速grep
传递它,并附加文本,如果它仍然没有找到。
例如
ENV_KEY=BLAH
ENV_VAL=foo
sed -i "/BLAH/s/^.*\\$/setenv ${ENV_KEY} ${ENV_VAL}/g" text.tmp
! grep -q "${ENV_KEY}" text.tmp && echo "setenv ${ENV_KEY} ${ENV_VAL}" >> text.tmp
这告诉sed
搜索字符串BLAH,如果找到它然后替换整行^.*$
。 -i
选项告诉sed
更新文件。
这可能适合你(GNU sed):
sed '/blah/h;//s/foo/newfoo/;$!b;G;/blah/!s/.$/&setenv blah newfoo/;t;P;d' file
如果blah
发现在保留空间(HS)中存储该行并用newfoo
替换foo
。 如果不是文件结尾,则打印每一行。 在文件结尾处将HS附加到模式空间并检查blah
。 如果没有找到附加setenv blah newfoo
并打印否则打印最后一行并删除剩余部分。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.