
举个例子,假设我有:
One, Two.
OnE, Two.
ONE, TWO.
我只想将全部大写的行替换为小写,这样我就得到:
One, Two.
OnE, Two.
one, two.
我在尝试:
gsed '/[a-z]/!c\L&'
它正确匹配行,但将其替换为:L&
One, Two.
OnE, Two.
L&
如何将其转换为小写?
我在 L 之前尝试了 2 或 3 个反斜杠,但它只是将它们放入输出中。
如果有更好的选择,我将使用 awk 或 tr 或其他一些实用程序。
另外,如果版本很重要:
gsed --version
gsed (GNU sed) 4.9
答案1
使用任何 POSIX awk:
$ awk '!/[[:lower:]]/ { $0=tolower($0) } 1' file
One, Two.
OnE, Two.
one, two.
答案2
我认为你需要使用s///
for&
来工作,例如:
$ sed -e '/[a-z]/!s/.*/\L&/' < test.txt
One, Two.
OnE, Two.
one, two.
您可以使用 Perl 执行相同或类似的操作(这可能在 GNU sed 不可用的情况下可用):
% perl -pe 's/.*/\L$&/ if not /[[:lower:]]/' < test.txt
One, Two.
OnE, Two.
one, two.
或者:
% perl -pe '$_ = lc if not /[[:lower:]]/' < test.txt
One, Two.
OnE, Two.
one, two.
答案3
与Perl
的三元运算符:
$ perl -ne 'print /[a-z]/ ? $_ : lc' file
One, Two.
OnE, Two.
one, two.
说明
操作员 | 意义 |
---|---|
perl |
可执行文件 |
-n |
解析当前文件内容,就像我们使用while (<>) ... |
-e |
Perl的e 表达 |
print |
打印 |
/regex/ ? : |
三元运算符,基于布尔结果的匹配regex |
/[a-z]/ |
如果有小写匹配... |
$_ |
...然后打印当前行的当前默认变量$_ |
lc |
l ...否则打印ower ase中的当前行c (隐式使用$_ ) |
答案4
这是我的(简短而甜蜜的)Perl 解决方案:
perl -wpe '$_ = lc unless m/[a-z]/' file.txt
高级解释:这只是说:在打印 file 中的每一行之前file.txt
,将该行转换为小写除非它包含所有小写字母。
您还可以替换m/[a-z]/
为tr/a-z//
,使其看起来像这样:
perl -wpe '$_ = lc unless tr/a-z//' file.txt
它们之间的区别在于,m/[a-z]/
旨在被评估为布尔值(即,它是否包含字符a
thru z
),而tr/a-z//
返回数字a
至范围内的字符数z
。 (如果它返回一个大于零的数字,则小写字母(即$_ = lc
)将不是发生。)
哪一个更好?我还没有对它们进行基准测试,但差异可能很小,所以最好使用您更熟悉的那个。
但请记住:该m/[a-z]/
方法使用[
和]
方括号,而该tr/a-z//
方法则没有,但以/
连续两个 s 结尾。记住两者可能有点麻烦,所以我建议您使用更容易记住的一个。