我当前正在运行此命令来审查缩进的待办事项列表。
sed -e 's/\(\s\+- \)\(.*\)/\1XXX/g'
这很好,只是我希望X
s 的数量与匹配字符的数量相匹配。我怎么做?正确的方法并不是特别需要使用sed。
当前示例输入:
- Hello World
- Earth
输出:
- XXX
- XXX
期望:
- XXXXXXXXXX
- XXXXX
答案1
Perl 解决方案:
perl -pe 's/^( *- )(.+)/$1."X"x length($2)/e'
这用于获取替换中"X" x length($2)
正确的 s 数量。X
测试输入:
- Hello World
- Earth
This is not - censored
输出:
- XXXXXXXXXXX
- XXXXX
This is not - censored
答案2
你也可以这样做sed
:
sed '/^[[:blank:]]*-[[:blank:]]/{
h
s///
s/./X/g
x
s/\([[:blank:]]*-[[:blank:]]\).*/\1/
G
s/\n//
}' infile
这会将行复制到h
旧缓冲区上,删除第一部分[[:blank:]]*-[[:blank:]]
,用 an 替换剩余字符X
,然后 ex
更改模式/保留空间,因此现在审查的字符串位于保留模式中,原始行返回到模式空间中。使用 删除该行的第二部分s/\(...\).*//
,将保留空间中的字符串附加到模式空间 ( G
) 并\n
删除 ewline 字符。因此,使用如下文件:
- line here
not - to be modified
- a b c d e
- another line-here
输出是:
- XXXXXXXXX
not - to be modified
- XXXXXXXXX
- XXXXXXXXXXXXXXXXX
如果您想删除空白字符并仅将非空白字符替换为X
:
sed '/^[[:blank:]]*-[[:blank:]]/{
h
s///
s/[[:blank:]]//g
s/./X/g
x
s/\([[:blank:]]*-[[:blank:]]\).*/\1/
G
s/\n//
}' infile
输出:
- XXXXXXXX
not - to be modified
- XXXXX
- XXXXXXXXXXXXXXXX
或者,在一行中包含gnu sed
:
sed -E '/^[ \t]*-[ \t]/{h;s///;s/[ \t]//g;s/./X/g;x;s/([ \t]*-[ \t]).*/\1/;G;s/\n//}' infile
^[[:blank:]]*-[[:blank:]]
根据您的需要调整正则表达式(即)。
答案3
$ awk '/^[ ]*- /{gsub(/[^ -]/,"X",$0)}1' <<EOM
- Hello
- World 2015
This is not - censored
EOM
- XXXXX
- XXXXX XXXX
This is not - censored
该awk
表达式查找以-
字符开头(在可选空格之后)的任何行。对于匹配行,该gsub()
命令将替换除空格和-
字符之外的所有字符。最后一个1
只是 的快捷方式{print $0}
,即重新打印整行。
编辑:由于您还需要删除/替换空白字符X
,所以除了进行额外的替换之外,我真的想不出更优雅的解决方案:
$ awk '/^[ ]*- /{gsub(/[^ -]/,"X",$0);gsub(/X X/,"XXX",$0)}1' <<EOM
- Hello World
- Earth
This is not - censored
EOM
- XXXXXXXXXXX
- XXXXX
This is not - censored
答案4
如果上述行中的空格不重要,您可以使用以下行
Q='Some things\n - Hellow World\n - Earth\nSome things Else'
echo -e "$Q" | awk '{ if ($0 ~ /^\s+-\s\w+/) print system("echo " $0 "| tr [:alnum:] x "); else print $0; }' | grep -v ^0$
$0 ~ /^\s+-\s\w+/
正如您提到的那样检查正则表达式。
system(...)
跑步重击里面的命令awk
grep -v ^0$
这部分是因为system(...)
返回退出代码状态。
我们可以摆脱grep -v ^0$与getline
I/O 语句但它更复杂。