从字符串中删除一个单词
Deleting a word from a string
我想从文件中删除特定单词。
假设文件名 agent_file.txt
包含以下字符串
-queues winall,dustat,envstat,netstat,iostat,winconfig,netwarestat,netwareconfig,pawmin,paw15,db2,sqlserver,vmstatvmw2,vmstatvm2,netstatvm,netstatvmw,vmstatvm,vmstatvmw,iostatvm,iostatvmw,envstatvm,envstatvmw,vmscpu,vmsdisk,vmsmem,vmstatvcw,process,winprocess
我只想删除这个文件中的字符或单词process
,所以我在Unix下使用下面的命令
perl -pi -e 's/process//g' agent_file.txt
输出将是
-queues winall,dustat,envstat,netstat,iostat,winconfig,netwarestat,netwareconfig,pawmin,paw15,db2,sqlserver,vmstatvmw2,vmstatvm2,netstatvm,netstatvmw,vmstatvm,vmstatvmw,iostatvm,iostatvmw,envstatvm,envstatvmw,vmscpu,vmsdisk,vmsmem,vmstatvcw,,win
该词被删除,但也删除了winprocess
的一部分。
如何只删除 process
以及前面的逗号 ,
(如果有)?
输出应该是
-queues winall,dustat,envstat,netstat,iostat,winconfig,netwarestat,netwareconfig,pawmin,paw15,db2,sqlserver,vmstatvmw2,vmstatvm2,netstatvm,netstatvmw,vmstatvm,vmstatvmw,iostatvm,iostatvmw,envstatvm,envstatvmw,vmscpu,vmsdisk,vmsmem,vmstatvcw,winprocess
分三步完成
sed 's/,process,/,/g;s/^process,//;s/,process$//'
测试位置:中间、开始或结束。
如果它是逗号分隔的,请使用它们来使它成为一个词。
perl -pi -e "s/, \s* process\s* , /, /g filename
如果逗号前后没有空格,则删除 \s*
使用逗号 (-F,
) 自动拆分 (-a
),完全避免逗号问题
perl -F, -lane 'print join ",", grep { not /^process$/ } @F' input > output
输入被 ,
分解为 @F
。 grep
过滤掉单词,其余的由 ,
加入
为了更改输入文件,添加 -i
并删除 > output
问题是第一个和最后一个单词有一个逗号,如果去掉就需要去掉,而其他的有两个逗号,需要留下一个。正则表达式的一种方法是进行两次传递,删除单词,然后删除额外的逗号(仍然要小心 first 和 last)。
或运行替换部分中的代码适用于select情况
echo "go,stay,ago,go,got,end,go" |
perl -pe's/(,)?\bgo\b(,)?/ && && ","/ge'
打印:stay,ago,got,end
。 /e
将替换端评估为 Perl 代码。
如果两个逗号都存在 ( &&
) 则 (&&
) 我们用逗号 (","
) 替换。
这是可行的,因为在 Perl 中 &&
returns the value
The ||
, //
and &&
operators return the last value evaluated (unlike C's ||
and &&
, which return 0 or 1).
这是一个 awk
解决方案。
awk 'BEGIN{OFS=FS=","} {for(i=1;i<=NF;i++) if($i=="process") $i=""} 1' file
这会将您的字段分隔符设置为输入和输出的逗号,然后遍历您的字段,检查是否与您感兴趣的字符串等价,如果匹配则清空该字段。最后的 1
是 "print the current line".
的 awk 简写
同样,可以按记录而不是按字段对输入数据进行切片:
awk 'BEGIN{ORS=RS=","} /^process$/{next} 1' file
或
awk 'BEGIN{ORS=RS=","} [=12=]=="process"{next} 1' file
这会使用逗号作为 RECORD 分隔符 (RS) 遍历您的输入,以便可以使用 awk 的记录感知来评估单个单词。您可以通过正则表达式或不通过正则表达式进行评估——正则表达式稍微慢一点,但似乎可以为您节省两个字符的输入。 :-)
使用 RS/ORS 的策略消除了您注意到的字段被清空但未被删除的问题。当逗号是记录分隔符时,跳过的记录会导致不显示记录分隔符,这更接近您在问题中包含的 "ideal" 输出。
最后一个选项可能是在您的 shell (ksh) 中执行此操作。这将具有最大的可移植性优势(您不必担心 perl 版本,无论 awk/sed 是 GNU 还是 BSD 或其他)。缺点是使用下面的方法,您的文件大小将受到系统内存的限制(可能还有可配置的限制)。
$ IFS=, read -A arr < file
$ for i in "${!arr[@]}"; do [[ "${arr[$i]}" == "process" ]] && unset arr[$i]; done
$ output=$(printf "%s," "${arr[@]}")
$ echo "${output%,}"
-queues winall,dustat,envstat,netstat,iostat,winconfig,netwarestat,netwareconfig,pawmin,paw15,db2,sqlserver,vmstatvmw2,vmstatvm2,netstatvm,netstatvmw,vmstatvm,vmstatvmw,iostatvm,iostatvmw,envstatvm,envstatvmw,vmscpu,vmsdisk,vmsmem,vmstatvcw,winprocess
请注意,仅需要 $output
变量才能去除 printf
生成的尾随逗号。另一种选择可能是更全局地设置 $IFS
:
$ IFS=,
$ echo "${arr[*]}"
-queues winall,dustat,envstat,netstat,iostat,winconfig,netwarestat,netwareconfig,pawmin,paw15,db2,sqlserver,vmstatvmw2,vmstatvm2,netstatvm,netstatvmw,vmstatvm,vmstatvmw,iostatvm,iostatvmw,envstatvm,envstatvmw,vmscpu,vmsdisk,vmsmem,vmstatvcw,winprocess
我应该指出,尽管出现,printf
选项并没有真正产生外部命令,因为 ksh 将 printf
作为内置实现。
也许像这样?
它搜索所有出现的 process
,使用单词边界来确保它不会作为另一个单词的一部分找到,并且还在前后匹配可选的逗号 ,
。如果找到两个逗号(process
位于列表中间),则匹配项将替换为单个逗号,如果只有一个(process
仅出现在列表的开头或结尾,则将其删除列表)
perl -pi -e 's/ ,? \b process \b ,? ) / =~ tr/,// > 1 ? ',' : '' /xge' agent_file.txt
awk '{sub(/process,/,"")}1' file
我想从文件中删除特定单词。
假设文件名 agent_file.txt
包含以下字符串
-queues winall,dustat,envstat,netstat,iostat,winconfig,netwarestat,netwareconfig,pawmin,paw15,db2,sqlserver,vmstatvmw2,vmstatvm2,netstatvm,netstatvmw,vmstatvm,vmstatvmw,iostatvm,iostatvmw,envstatvm,envstatvmw,vmscpu,vmsdisk,vmsmem,vmstatvcw,process,winprocess
我只想删除这个文件中的字符或单词process
,所以我在Unix下使用下面的命令
perl -pi -e 's/process//g' agent_file.txt
输出将是
-queues winall,dustat,envstat,netstat,iostat,winconfig,netwarestat,netwareconfig,pawmin,paw15,db2,sqlserver,vmstatvmw2,vmstatvm2,netstatvm,netstatvmw,vmstatvm,vmstatvmw,iostatvm,iostatvmw,envstatvm,envstatvmw,vmscpu,vmsdisk,vmsmem,vmstatvcw,,win
该词被删除,但也删除了winprocess
的一部分。
如何只删除 process
以及前面的逗号 ,
(如果有)?
输出应该是
-queues winall,dustat,envstat,netstat,iostat,winconfig,netwarestat,netwareconfig,pawmin,paw15,db2,sqlserver,vmstatvmw2,vmstatvm2,netstatvm,netstatvmw,vmstatvm,vmstatvmw,iostatvm,iostatvmw,envstatvm,envstatvmw,vmscpu,vmsdisk,vmsmem,vmstatvcw,winprocess
分三步完成
sed 's/,process,/,/g;s/^process,//;s/,process$//'
测试位置:中间、开始或结束。
如果它是逗号分隔的,请使用它们来使它成为一个词。
perl -pi -e "s/, \s* process\s* , /, /g filename
如果逗号前后没有空格,则删除 \s*
使用逗号 (-F,
) 自动拆分 (-a
),完全避免逗号问题
perl -F, -lane 'print join ",", grep { not /^process$/ } @F' input > output
输入被 ,
分解为 @F
。 grep
过滤掉单词,其余的由 ,
为了更改输入文件,添加 -i
并删除 > output
问题是第一个和最后一个单词有一个逗号,如果去掉就需要去掉,而其他的有两个逗号,需要留下一个。正则表达式的一种方法是进行两次传递,删除单词,然后删除额外的逗号(仍然要小心 first 和 last)。
或运行替换部分中的代码适用于select情况
echo "go,stay,ago,go,got,end,go" |
perl -pe's/(,)?\bgo\b(,)?/ && && ","/ge'
打印:stay,ago,got,end
。 /e
将替换端评估为 Perl 代码。
如果两个逗号都存在 ( &&
) 则 (&&
) 我们用逗号 (","
) 替换。
这是可行的,因为在 Perl 中 &&
returns the value
The
||
,//
and&&
operators return the last value evaluated (unlike C's||
and&&
, which return 0 or 1).
这是一个 awk
解决方案。
awk 'BEGIN{OFS=FS=","} {for(i=1;i<=NF;i++) if($i=="process") $i=""} 1' file
这会将您的字段分隔符设置为输入和输出的逗号,然后遍历您的字段,检查是否与您感兴趣的字符串等价,如果匹配则清空该字段。最后的 1
是 "print the current line".
同样,可以按记录而不是按字段对输入数据进行切片:
awk 'BEGIN{ORS=RS=","} /^process$/{next} 1' file
或
awk 'BEGIN{ORS=RS=","} [=12=]=="process"{next} 1' file
这会使用逗号作为 RECORD 分隔符 (RS) 遍历您的输入,以便可以使用 awk 的记录感知来评估单个单词。您可以通过正则表达式或不通过正则表达式进行评估——正则表达式稍微慢一点,但似乎可以为您节省两个字符的输入。 :-)
使用 RS/ORS 的策略消除了您注意到的字段被清空但未被删除的问题。当逗号是记录分隔符时,跳过的记录会导致不显示记录分隔符,这更接近您在问题中包含的 "ideal" 输出。
最后一个选项可能是在您的 shell (ksh) 中执行此操作。这将具有最大的可移植性优势(您不必担心 perl 版本,无论 awk/sed 是 GNU 还是 BSD 或其他)。缺点是使用下面的方法,您的文件大小将受到系统内存的限制(可能还有可配置的限制)。
$ IFS=, read -A arr < file
$ for i in "${!arr[@]}"; do [[ "${arr[$i]}" == "process" ]] && unset arr[$i]; done
$ output=$(printf "%s," "${arr[@]}")
$ echo "${output%,}"
-queues winall,dustat,envstat,netstat,iostat,winconfig,netwarestat,netwareconfig,pawmin,paw15,db2,sqlserver,vmstatvmw2,vmstatvm2,netstatvm,netstatvmw,vmstatvm,vmstatvmw,iostatvm,iostatvmw,envstatvm,envstatvmw,vmscpu,vmsdisk,vmsmem,vmstatvcw,winprocess
请注意,仅需要 $output
变量才能去除 printf
生成的尾随逗号。另一种选择可能是更全局地设置 $IFS
:
$ IFS=,
$ echo "${arr[*]}"
-queues winall,dustat,envstat,netstat,iostat,winconfig,netwarestat,netwareconfig,pawmin,paw15,db2,sqlserver,vmstatvmw2,vmstatvm2,netstatvm,netstatvmw,vmstatvm,vmstatvmw,iostatvm,iostatvmw,envstatvm,envstatvmw,vmscpu,vmsdisk,vmsmem,vmstatvcw,winprocess
我应该指出,尽管出现,printf
选项并没有真正产生外部命令,因为 ksh 将 printf
作为内置实现。
也许像这样?
它搜索所有出现的 process
,使用单词边界来确保它不会作为另一个单词的一部分找到,并且还在前后匹配可选的逗号 ,
。如果找到两个逗号(process
位于列表中间),则匹配项将替换为单个逗号,如果只有一个(process
仅出现在列表的开头或结尾,则将其删除列表)
perl -pi -e 's/ ,? \b process \b ,? ) / =~ tr/,// > 1 ? ',' : '' /xge' agent_file.txt
awk '{sub(/process,/,"")}1' file