在尝试找到 this sed question 的答案时,我想出了一个我无法理解的奇怪行为。
假设我有一个名为data
$> cat data
foo.png
abCd.png
bar.png
baZ.png
任务是使用sed在行中将所有带有大写ASCII字符的行替换为小写。所以输出应该是:
$> cat data
foo.png
abcd.png
bar.png
baz.png
该解决方案应该适用于非gnu sed,也就像在Mac上的sed一样
我尝试将这个嵌入式awk放入sed的替换部分:
sed -E 's/[^ ]*[A-Z][^ ]*.png/'$(echo \&|awk '{printf("<%s>[%s]",$0, tolower($0))}')'/' data
奇怪的是,这输出了:
foo.png
<abCd.png>[abCd.png]
bar.png
<baZ.png>[baZ.png]
正如你所看到的那样,sed正在拾取带有大写字母的正确行,并且那也达到awk但awk的tolower()
函数失败并产生与输入相同的文本。
shell专家可以解释这种奇怪的行为。
答案 0 :(得分:10)
您的awk
命令在sed
命令之前运行,而不是作为sed
命令的子进程运行,因此awk
仅接收文字&符作为其输入,如结果输出
<&>[&]
然后将此字符串嵌入到sed
作为其参数接收的字符串中,从中可以明显看出sed
产生输出的原因。
事件顺序是
shell看到此命令行
sed -E 's/[^ ]*[A-Z][^ ]*.png/'$(echo \&|awk '{printf("<%s>[%s]",$0, tolower($0))}')'/' data
它处理命令替换(其中awk
将&
转换为<&>[&]
),以生成中间命令行
sed -E 's/[^ ]*[A-Z][^ ]*.png/'<&>[&]'/' data
然后shell使用命令sed
执行s/[^ ]*[A-Z][^ ]*.png/<&>[&]/
答案 1 :(得分:6)
sed 'y/ABCDEFGHIJKLMNOPQRSYUVWXYZ/abcdefghijklmnopqrstuvwxyz/'
答案 2 :(得分:3)
也许tr
正是你真正想要的?
tr A-Z a-z file
sed
等价物将是:
sed -e 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/'
您似乎不能使用字符范围表示法(A-Z
和/或[A-Z]
),这是不幸的,也很烦人。
答案 3 :(得分:2)
我99%确定你不能直接在Mac / BSD sed
上执行此操作而没有特别难看的东西(sed -e s/A/a/g -e s/B/b/g ...
),所以除非找到sed
解决方案,这是一个awk
,它内联:
awk '{print tolower($0) >FILENAME}' data
答案 4 :(得分:2)
如果你真的需要在普通sed
中转换为小写,那么它可能会相当丑陋:
sed -e s/A/a/g -e s/B/b/g -e s/C/c/g -e s/D/d/g -e s/E/e/g -e s/F/f/g -e s/G/g/g -e s/H/h/g -e s/I/i/g -e s/J/j/g -e s/K/k/g -e s/L/l/g -e s/M/m/g -e s/N/n/g -e s/O/o/g -e s/P/p/g -e s/Q/q/g -e s/R/r/g -e s/S/s/g -e s/T/t/g -e s/U/u/g -e s/V/v/g -e s/W/w/g -e s/X/x/g -e s/Y/y/g -e s/Z/z/g
编辑:没关系,@ Bruce Barnett的解决方案更好
答案 5 :(得分:2)
你真的确定你不能使用Perl吗?
perl -pi.bak -e 's/([^ ]*[A-Z][^ ]*\.png)/\l\1/' file
这是反斜杠 - 指定小写,反斜杠 - 重复第一个匹配组。
答案 6 :(得分:1)
根据一些良好的答案,这里有一个解决方案我可以提出:
sed -i.bak 'y/'$(awk 'BEGIN {for(i=65; i<=90; i++) printf("%c", i); printf("/");
for(i=97; i<=122; i++) printf("%c", i)}')'/' data