使用sed将一些大写字母替换为小写字母

4
我是一位有用的助手,可以为您进行文本翻译。以下是需要翻译的内容:

我有一个名为file.txt的文件,其中包含绝对路径。它看起来像这样:

J:/Folder/inner
J:/Folder/inner2

首先,我想写一个bash脚本,将J:/替换为/cygdrive/j/。所以我像这样做:

sed -i 's/J:\//\/cygdrive\/j\//g' file.txt                    

现在我想要更复杂的东西:绝对路径不必以J开头-它们可以以CDE等开头。
我想做与上面相同的事情,只是我不知道第一个字母是什么。例如:C:/Folder/inner将变为/cygdrive/c/Folder/innerD:/Folder/inner将变为/cygdrive/d/Folder/inner
我知道我需要使用正则表达式来实现这一点,但我还没有找到方法。你知道怎样才能得到我想要的吗?

2个回答

4
我会使用 Awk 解决这个问题,使用 tolower() 进行小写转换,并将字段分隔符设置为 :,然后打印其余的字段。
awk -F: '{print "/cygdrive/"tolower($1)""$2}' file.txt

这基本上意味着在将$1值转换为小写(J)后,打印出该值并在其后附加$2(字符串的其余部分)。 “”只表示没有任何字符的空字符串。您也可以将它们删除。

一旦您发现名称已经正确替换,请更改源文件本身。

awk -F: '{print "/cygdrive/"tolower($1)""$2}' file.txt > temp && mv temp file.txt

在下面的示例文件中:
J:/Folder/inner
J:/Folder/inner2
C:/Folder/inner
D:/Folder/inner

该命令将生成一个输出文件。
/cygdrive/j/Folder/inner
/cygdrive/j/Folder/inner2
/cygdrive/c/Folder/inner
/cygdrive/d/Folder/inner

如果你已经安装了,perl 中还有另一种变体:

perl -lne 'print "/cygdrive/\L$1$2" if /(.):(.+)/' file.txt

现在尝试了一下,运行这些脚本时出现以下错误:awk:'{print. awk: ^表达式中存在无效字符'''. - Mark
你使用的是哪个版本的 Awk?你能输出 awk --version 吗? - Inian
@Mark:我在发布之前检查过它,一切正常。你是如何在终端上执行该命令的? - Inian
1
@Mark:小心DOS Unicode引号,使用正确的shell引号。如果您可以在某个地方上传截图并在此处链接它。 - Inian
2
@Mark:这正是我在之前评论中提到的问题,“''”是Unicode引用,无法在bash shell中使用,请在Awk周围使用shell引号“''”。 - Inian
显示剩余5条评论

4

要使用 sed 实现,你需要支持更改大小写的功能,这是 GNU sed 提供的。因此,这不是一个便携式的解决方案。

$ cat file.txt 
J:/Folder/inner
J:/Folder/inner2
C:/Folder/inner
D:/Folder/inner

$ sed -E 's#^(.):#/cygdrive/\l\1#' file.txt 
/cygdrive/j/Folder/inner
/cygdrive/j/Folder/inner2
/cygdrive/c/Folder/inner
/cygdrive/d/Folder/inner
  • -E 用于启用ERE,在这种情况下避免必须转义 ()
    • 有些版本可能只支持 -r 而不是 -E
  • ^(.): 匹配一行开头的字符和 :
    • 根据需要使用 ^([A-Z]):^([A-Za-z]): 仅匹配字母
  • /cygdrive/\l\1 在替换部分中,将使用字符串 /cygdrive/ 和捕获字符的小写版本
  • 请注意使用 # 作为分隔符,有助于避免在搜索/替换部分中转义 /
    • 可以使用除 \ 和换行符之外的任何字符
  • 在解决方案按预期工作时添加 -i

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接