我有一个像这样的字符串:
#
pap
基本上翻译为\t#\n\tpap
,我想将其替换为:
#
pap
python
转换为\t#\n\tpap\n\tpython
。
在很多方面使用sed
尝试了这一点,但它不起作用可能是因为sed
以不同的方式使用新行。我尝试过:
sed -i "s/\t#\n\tpap/\t#\tpython\n\tpap/" /etc/freeradius/sites-available/default
......以及许多不同的其他方式,没有结果。我知道在这种情况下如何更换?
答案 0 :(得分:6)
这可能适合你(GNU sed):
sed '/^\t#$/{n;/^\tpap$/{p;s//\tpython/}}' file
如果某一行仅包含\t#
,则如果下一行仅包含\tpap
,则将其替换为\tpython
并将其打印出来。
答案 1 :(得分:4)
用gawk尝试这一行:
awk -v RS="\0" -v ORS="" '{gsub(/\t#\n\tpap/,"yourNEwString")}7' file
如果你想让sed
处理新行,你必须先阅读整个文件:
sed ':a;N;$!ba;s/\t#\n\tpap/NewString/g' file
答案 2 :(得分:3)
GNU sed
解决方案不需要立即读取整个文件:
sed '/^\t#$/ {n;/^\tpap$/a\\tpython'$'\n''}' file
/^\t#$/
匹配仅注释行(完全匹配\t#
),在这种情况下(仅)执行整个{...}
表达式:
n
加载并打印 next 行。/^\tpap/
与\tpap
的下一行完全匹配。a\\tpython
将在跟随行之前输出\n\tpython
- 请注意拼接的换行符($'\n'
)需要发出传递给a
命令的文本的结尾(您可以使用多个-e
选项)。(顺便说一下:使用 BSD sed
(OS X),它会变得很麻烦,因为
\n
和\t
不受直接支持,必须以ANSI C引用的文字拼接。前导空格总是从a
命令的text参数中删除,因此必须使用替换方法:s//&\'$'\n\t'python'/
用自己替换pap
行加上要追加的行:
sed '/^'$'\t''#$/ {n; /^'$'\t''pap$/ s//&\'$'\n\t'python'/;}' file
)
awk
解决方案(符合POSIX标准),不需要一次阅读整个文件:
awk '{print} /^\t#$/ {f=1;next} f && /^\tpap$/ {print "\tpython"} {f=0}' file
{print}
:打印每个输入行/^\t#$/ {f=1;next}
:如果找到仅有注释的行(完全匹配f
),则将标记1
(对于'找到')设置为\t#
并转到下一行。f && /^\tpap$/ {print "\tpython"}
:如果一行前面有注释行并且与\tpap
完全匹配,则输出额外的行\tpython
。{f=0}
:重置指示仅注释行的标志。答案 3 :(得分:1)
一些纯粹的bash
解决方案:
in=$'\t#\n\tpap\n' # input string
echo "${in/$'\t#\n\tpap\n'/$'\t#\n\tpap\n\tpython\n'}"
pap
后跟\n
,而没有假设\t#
之前的内容,可能会导致误报。\t#\n\tpap
中\n
总是封闭,echo "${in/$'\n\t#\n\tpap\n'/$'\n\t#\n\tpap\n\tpython\n'}"
可以有效地运作;否则,见下文。=~
运算符进行正则表达式匹配时,功能强大但很冗长: =~
运算符在右侧支持扩展正则表达式,因此可以实现更灵活,更强大的匹配:
in=$'\t#\n\tpap' # input string
# Search string and string to append after.
search=$'\t#\n\tpap'
append=$'\n\tpython'
out=$in # Initialize output string to input string.
if [[ $in =~ ^(.*$'\n')?("$search")($'\n'.*)?$ ]]; then # perform regex matching
out=${out/$search/$search$append} # replace match with match + appendage
fi
echo "$out"