我只想将文件中的最后一个字符串“ delay”替换为“ ens_delay”,并删除最后一个字符串之前的其他字符串:
输入文件:
alpha_notify_teta=''
alpha_notify_check='YES'
text='CRDS'
delay=''
delay=''
delay=''
textfileooooop=''
alpha_enable='YES'
alpha_hostnames=''
alpha_orange='YES'
alpha_orange_interval='300'
alpha_notification_level='ALL'
expression='YES'
delay='9'
textfileooooop=''
alpha_enable='YES'
alpha_hostnames=''
输出文件:(期望值)
alpha_notify_teta=''
alpha_notify_check='YES'
text='CRDS'
textfileooooop=''
alpha_enable='YES'
alpha_hostnames=''
alpha_orange='YES'
alpha_orange_interval='300'
alpha_notification_level='ALL'
expression='YES'
ens_delay='9'
textfileooooop=''
alpha_enable='YES'
alpha_hostnames=''
这是我的第一个命令,但是它不起作用,因为只有在我延迟到最后一行时它才起作用。
sed -e '$,/delay/ s/delay/ens_delay/'
我的第二个命令将删除所有包含“ delay”的行,甚至“ ens_delay”也将被删除。
sed -i '/delay/d'
谢谢
答案 0 :(得分:3)
这可能对您有用(GNU sed):
sed '/^delay=/,$!b;/^delay=/!H;//{x;s/^[^\n]*\n\?//;/./p;x;h};$!d;x;s/^/ens_/' file
在delay=
开头的第一行之前的行应正常打印。否则,以delay=
开头的行将存储在保留空间中,而没有以delay=
开头的后续行将附加到该行。如果保留空间已经包含这些行,则删除第一行,并在保留空间之前用当前行替换剩余的行。在文件末尾,将保留空间的第一行修改为在字符串ens_
之前加上前缀,然后打印整个保留空间。
答案 1 :(得分:0)
您无法使用sed做这种事情。 sed无法“向前看”并判断该模式是否还有更多匹配项。您可以回顾一下,但这不足以解决此问题。
此perl脚本将解决该问题:
#!/usr/bin/perl
use strict;
use warnings;
my ($seek, $replacement, $last, @new) = (shift, shift, 0);
open(my $fh, shift) or die $!;
my @l = <$fh>;
close($fh) or die $!;
foreach (reverse @l){
if(/$seek/){
if ($last++ == 0){
s/$seek/$replacement/;
} else {
next;
}
}
unshift(@new, $_);
}
print join "", @new;
致电方式:
./script delay= ens_delay= inputfile
我选择完全消除要删除的行,而不是将它们折叠成一个空白行。如果确实需要这样做,则要复杂一点:任何连续集中的第一行(或最后一行)都必须插入到输出列表中,并且您必须跟踪这是否刚刚完成,以便知道是否下次也要推。
您还可以使用awk,python或任何其他多种语言来解决此问题。只是不安。
答案 2 :(得分:0)
拥有这个怪物:
sed -e "1,$(expr $(sed -n '/^delay=/=' your_file.txt | tail -1) - 1)"'s/^delay=.*$//' \
-e 's/^delay=/ens_delay=/' your_file.txt
这里:
sed -n '/^delay=/=' your_file.txt | tail -1
返回遇到的模式的最后一行 number (我们将其命名为X
)expr
用于获取X-1
行"1,X-1"'[command]'
的意思是“在第一行和X-1行之间执行此命令(我使用双引号使扩展完成)'s/^delay=.*$//'
所说的[command]
-e 's/^delay=/ens_delay=/'
下一个要执行的表达式(仅在最后一行出现)输出:
alpha_notify_teta=''
alpha_notify_check='YES'
text='CRDS'
textfileooooop=''
alpha_enable='YES'
alpha_hostnames=''
alpha_hsm_backup_notification='YES'
alpha_orange='YES'
alpha_orange_interval='300'
alpha_notification_level='ALL'
expression='YES'
ens_delay='9'
textfileooooop=''
alpha_enable='YES'
alpha_hostnames=''
alpha_hsm_backup_notification='YES'
如果您要删除行而不是将其留空:
sed -e "1,$(expr $(sed -n '/^delay=/=' your_file.txt | tail -1) - 1)"'{/^delay=.*$/d}' \
-e 's/^delay=/ens_delay=/' your_file.txt
答案 3 :(得分:0)
正如其他地方所提到的,sed无法知道哪个子字符串是最后一个子字符串。但是awk可以跟踪数组中的内容。例如,以下内容将删除所有重复的作业,并要求您进行替换:
awk 'BEGIN{FS=OFS="="} $1=="delay"{$1="ens_delay"} !($1 in a){o[++i]=$1} {a[$1]=$0} END{for(x=0;x<i;x++) printf "%s\n",a[o[x]]}' inputfile
或者,为了便于阅读/注释而进行了分拆:
BEGIN {
FS=OFS="=" # set the field separator, to help isolate the left hand side
}
$1=="delay" {
$1="ens_delay" # your field substitution
}
!($1 in a) {
o[++i]=$1 # if we haven't seen this variable, record its position
}
{
a[$1]=$0 # record the value of the last-seen occurrence of this variable
}
END {
for (x=0;x<i;x++) # step through the array,
printf "%s\n",a[o[x]] # printing the last-seen values, in the order
} # their variable was first seen in the input file.
您可能不在乎变量的顺序。如果是这样,则以下内容可能会更简单:
awk 'BEGIN{FS=OFS="="} $1=="delay"{$1="ens_delay"} {o[$1]=$0} END{for(i in o) printf "%s\n", o[i]}' inputfile
这只是将最后看到的行存储在键为变量名的数组中,然后以未知顺序打印出数组的内容。
答案 4 :(得分:0)
假设我正确理解了您的规格,这应该可以满足您的需求。鉴于文件x
,
$: last=$( grep -n delay x|tail -1|sed 's/:.*//' )
此grep
是所有带有delay
的行的文件,并以带冒号的行号返回它们。 tail -1
抓住了这些行的最后一行,而忽略了所有其他行。 sed 's/:.*//'
去除冒号和实际行内容,仅保留数字(此处为14
。)
所有评估结果都将14分配为$last
。
$: sed '/delay/ { '$last'!d; '$last' s/delay/ens_delay/; }' x
alpha_notify_teta=''
alpha_notify_check='YES'
text='CRDS'
textfileooooop=''
alpha_enable='YES'
alpha_hostnames=''
alpha_orange='YES'
alpha_orange_interval='300'
alpha_notification_level='ALL'
expression='YES'
ens_delay='9'
textfileooooop=''
alpha_enable='YES'
alpha_hostnames=''
不好意思的道歉。这样做是使用$last
的值写入脚本,以便结果对sed
如下所示:
$: sed '/delay/ { 14!d; 14 s/delay/ens_delay/; }' x
sed
读取前导数字作为行选择器,因此此命令脚本的作用-
首先,sed
会自动打印行,除非告知您不这样做,因此默认情况下它将只打印每行。该脚本对此进行了修改。
/delay/ {
... }
是基于模式的记录选择器。它将{}
之间的命令应用于与/delay/
匹配的所有行,这就是为什么它不需要另一个grep
的原因-它自己处理。在curl内,脚本执行两件事。
首先,14!d
说(仅当该行具有delay
时,才表示)如果行号为14,则不要 ({{1} })!
删除记录。由于其他所有带有d
的行都不会成为第14行(或先前命令创建的最后一个的任何值),因此这些行将被delay
删除,这将自动重新启动循环并读取下一个记录。
第二,如果行号 为14,则不会d
删除,因此将前进到d
,这将更新您的值。
对于所有与s/delay/ens_delay/
不匹配的行,/delay/
仅按原样打印它们。