使用 sed 去除单个大写字母后的空格

使用 sed 去除单个大写字母后的空格

我正在编写一个 bash 脚本来自动生成一些其他文件,并且我必须以某种方式格式化一些字符串。具体来说,我遇到的最后一个问题是格式化一个包含单独大写字母和以大写字母开头的单词的字符串。例如:

O S D Settings需要成为OSD Settings

我有一个 sed 命令可以删除第一个空格,但它也会删除“D”(即O S D Settings-> OS Settings)。这个命令是:

O S D Settings | sed 's/ \([A-Z]\)* \(A-Za-z]*\)/\1/g'

有谁知道如何删除各个大写字母之间的空格而不丢失任何字母?

答案1

这会处理诸如A B Chadwick和 之类的名称A B C D'Souza

诸如A B cde和 之类的文本A B CDE不会被修改。

它使用两个临时空字符\x00来标记行中的更改(每个名称),删除空格。

:N并且:S分支到标签(任何名称都可以)
t并且b是分支指令。
t在上一个命令中成功替换后分支s/../../
b无条件分支。

sed -r ":N                                                # loop per name
         /(\<[A-Z]\> )+[A-Z][a-z']/{                      # line needs action
             s/((\<[A-Z]\> )+)([A-Z][a-z'])/\x00\1\x00\3/ # add \x00 markers
            :S                                            # loop per space
             s/(\x00[A-Z]+) (\<[A-Z]\>)/\1\2/             # delete a space
             t S                                          # any more spaces? 
             b N                                          # any more names?
         }; s/\x00//g"                                    # remove \x00

答案2

这很棘手sed,但如果perl可以的话你可以这样做

echo O S D Settings | perl -p -e 's/(\b[A-Z]) (?=.([^\w]|$))/$1/g'

这很困难,sed因为它不支持前瞻断言。

测试:

echo O S D | perl -p -e 's/(\b[A-Z]) (?=.([^\w]|$))/$1/g'
echo O S D Settings | perl -p -e 's/(\b[A-Z]) (?=.([^\w]|$))/$1/g'
echo O S D. | perl -p -e 's/(\b[A-Z]) (?=.([^\w]|$))/$1/g'
echo One O DDE T. S Asdf Q R Tee | perl -p -e 's/(\b[A-Z]) (?=.([^\w]|$))/$1/g'
echo O S D\  | perl -p -e 's/([A-Z]) (?=.([^\w]|$))/$1/g'

如果你想要一个草率的解决方案sed,请尝试

echo O S D Settings | sed -e 's/ \([A-Z]\) \([A-Z] \)/\1\2/g'

这适用于您的示例,但不适用于其他情况。

测试:

echo O S D | sed -e 's/ \([A-Z]\) \([A-Z] \)/\1\2/g'
echo O S D Settings | sed -e 's/ \([A-Z]\) \([A-Z] \)/\1\2/g'
echo O S D. | sed -e 's/ \([A-Z]\) \([A-Z] \)/\1\2/g'
echo One O DDE T. S Asdf Q R Tee | sed -e 's/ \([A-Z]\) \([A-Z] \)/\1\2/g'
echo O S D\  | sed -e 's/ \([A-Z]\) \([A-Z] \)/\1\2/g'

答案3

这可能对你有用:

echo "O S D Settings and B T W and A B C D'Souza too F Y I" |
sed ':a;s/\(\<[[:upper:]]\>\) \(\<[[:upper:]]\>\([^'\'']\|$\)\)/\1\n\2/g;ta;s/\n//g'
OSD Settings and BTW and ABC D'Souza too FYI

解释:

使用原始字符串中不存在的字符替换要删除的空格,然后在整个字符串中删除所选字符。\n是一个很好的候选者,因为它不能正常存在,因为它被 sed 用作行分隔符。

答案4

我最终只是使用 sed 和管道来获得一个对我来说很容易理解的语句:

echo O S D Settings | sed 's/\([A-Z][^ ]\)/_\1/g' | sed 's/ //g' | sed 's/_/ /g'

这一切所做的就是用下划线替换我不需要的空格,然后删除它们。感谢所有的答案!

相关内容