Bash 用一个标签进行分组

Bash 用一个标签进行分组,bash,sed,Bash,Sed,我想使用test.md文件: /Dropbox/Notes/test.md:TODO something to eat or todo /Dropbox/Notes/test.md:todo something blue /Dropbox/Notes/test.md:Todo mixed 到 到目前为止,我想出了这个命令 cat test.md | sed "s/\(.*\):\(TODO\) \(.*\)/\2 \3 file\:/\1/gp" 但是,我得到一个“s的未知选项”错误

我想使用test.md文件:

/Dropbox/Notes/test.md:TODO something to eat or todo
/Dropbox/Notes/test.md:todo something blue
/Dropbox/Notes/test.md:Todo mixed

到目前为止,我想出了这个命令

cat test.md | sed  "s/\(.*\):\(TODO\) \(.*\)/\2 \3    file\:/\1/gp"
但是,我得到一个“s的未知选项”错误。此外,我还希望路径描述由一个选项卡分隔


我使用的是GNU sed。

如果您想要格式良好的输出,使用
awk
可能会更容易:

awk -F: '{printf "%-40sfile://%s\n", $2, $1}' inputfile
-40
将第一个字段的宽度指定为40个字符,并用左对齐
s
表示它是一个字符串

对于您的输入,它将产生:

TODO something to eat or todo           file:///Dropbox/Notes/test.md
todo something blue                     file:///Dropbox/Notes/test.md
Todo mixed                              file:///Dropbox/Notes/test.md
您的
sed
表达式不起作用,因为替换中有一个未替换的
/

sed  "s/\(.*\):\(TODO\) \(.*\)/\2 \3    file:\/\1/gp"
                                              ^

(您转义了
而不是斜杠。)

如果您想要格式良好的输出,使用
awk
可能更容易:

awk -F: '{printf "%-40sfile://%s\n", $2, $1}' inputfile
-40
将第一个字段的宽度指定为40个字符,并用左对齐
s
表示它是一个字符串

对于您的输入,它将产生:

TODO something to eat or todo           file:///Dropbox/Notes/test.md
todo something blue                     file:///Dropbox/Notes/test.md
Todo mixed                              file:///Dropbox/Notes/test.md
您的
sed
表达式不起作用,因为替换中有一个未替换的
/

sed  "s/\(.*\):\(TODO\) \(.*\)/\2 \3    file:\/\1/gp"
                                              ^

(您转义了
而不是斜杠。)

您的
sed
脚本中的直接问题是,替换文本以及
s//
命令中都有斜杠:

sed  "s/\(.*\):\(TODO\) \(.*\)/\2 \3    file\:/\1/gp"
       ^                      ^               ^  ^
       1                      2               3  4
斜杠3是这里的闯入者。您可以通过几种不同的方式修复它:

sed -e 's/\(.*\):\([Tt][Oo][Dd][Oo]\) \(.*\)/\2 \3    file\:\/\/\1/g'
sed -e 's%\(.*\):\([Tt][Oo][Dd][Oo]\) \(.*\)%\2 \3    file\://\1%g'
第一个使用反斜杠来转义作为替换字符串一部分的斜杠(固定代码还为
文件://
前缀引入了两个斜杠)。第二个将分隔符从斜杠更改为百分比
%
。我会这样做的。我还将整个表达式括在单引号中,这通常更安全—shell不解释单引号中的任何字符。我还对
ToDo
进行了匹配,不区分大小写。根据您的
sed
中的额外功能,可能还有其他方法可以做到这一点,但它在按图所示编写时仍然有效

我删除了
p
限定符,以防止为每个匹配的输入行获得两行输出。如果只需要匹配行,则需要优化操作以:

sed -n -e '/\(.*\):\([Tt][Oo][Dd][Oo]\) \(.*\)/ s%%\2 \3    file\://\1%gp'

现在,模式仅与ToDo行匹配,修改后的版本已写入。

您的
sed
脚本中的直接问题是,替换文本以及
s///
命令中都有斜杠:

sed  "s/\(.*\):\(TODO\) \(.*\)/\2 \3    file\:/\1/gp"
       ^                      ^               ^  ^
       1                      2               3  4
sed 's|\(.*\):\([tT][oO][dD][oO][^[:space:]]*\)[[:space:]]\(.*\)|\2 \3 file://\1|' YourFile
斜杠3是这里的闯入者。您可以通过几种不同的方式修复它:

sed -e 's/\(.*\):\([Tt][Oo][Dd][Oo]\) \(.*\)/\2 \3    file\:\/\/\1/g'
sed -e 's%\(.*\):\([Tt][Oo][Dd][Oo]\) \(.*\)%\2 \3    file\://\1%g'
第一个使用反斜杠来转义作为替换字符串一部分的斜杠(固定代码还为
文件://
前缀引入了两个斜杠)。第二个将分隔符从斜杠更改为百分比
%
。我会这样做的。我还将整个表达式括在单引号中,这通常更安全—shell不解释单引号中的任何字符。我还对
ToDo
进行了匹配,不区分大小写。根据您的
sed
中的额外功能,可能还有其他方法可以做到这一点,但它在按图所示编写时仍然有效

我删除了
p
限定符,以防止为每个匹配的输入行获得两行输出。如果只需要匹配行,则需要优化操作以:

sed -n -e '/\(.*\):\([Tt][Oo][Dd][Oo]\) \(.*\)/ s%%\2 \3    file\://\1%gp'
现在,模式只匹配ToDo行,修改后的版本已写入

sed 's|\(.*\):\([tT][oO][dD][oO][^[:space:]]*\)[[:space:]]\(.*\)|\2 \3 file://\1|' YourFile
使用posix版本(-GNU sed上的e),其中没有genreic大写/小写字母模式选项 使用
|
作为分隔符,允许在
文件:

也可以是(对于此示例结构)

使用posix版本(-GNU sed上的e),其中没有genreic大写/小写字母模式选项 使用
|
作为分隔符,允许在
文件:

也可以是(对于此示例结构)


您可以将
sed
与不同的分隔符集一起使用,然后通过指定特定的分隔符进行精确打印,将其输送到

$ sed 's|\([^:]*\):\(.*\)|\2,file:///\1|' file | column -ts','
TODO something to eat or todo  file:////Dropbox/Notes/test.md
todo something blue            file:////Dropbox/Notes/test.md
Todo mixed                     file:////Dropbox/Notes/test.md
  • 我们使用
    |
    作为
    sed
    分隔符
  • 使用捕获组,我们从输入中捕获两部分(文件名和文本)
  • 在替换中,我们添加了必要的文本以及分隔符
  • 分隔符用于
    ,用于分隔两个上下文以进行打印
您可以将
sed
与不同的分隔符集一起使用,然后通过指定特定的分隔符进行精确打印,将其输送到

$ sed 's|\([^:]*\):\(.*\)|\2,file:///\1|' file | column -ts','
TODO something to eat or todo  file:////Dropbox/Notes/test.md
todo something blue            file:////Dropbox/Notes/test.md
Todo mixed                     file:////Dropbox/Notes/test.md
  • 我们使用
    |
    作为
    sed
    分隔符
  • 使用捕获组,我们从输入中捕获两部分(文件名和文本)
  • 在替换中,我们添加了必要的文本以及分隔符
  • 分隔符用于
    ,用于分隔两个上下文以进行打印
awk
在这种情况下更好。
awk
在这种情况下更好。它们都是这样,因为最后的
p
没有
-n
选项。我承认从问题中复制了太多代码。他们都这样做了,因为最后的
p
没有
-n
选项。我承认从问题中复制了太多代码。这个输出生成空格作为分隔符。我能把它改成一个真正的制表符吗?@N\u 2如果你有gnu sed,你可以使用
sed的| \([^:]*\):\(.*)|\2\t文件:///\1 |'文件
,如果你想要制表符分离,但它作为列输出并不漂亮。请注意,使用此选项,您将不会将其管道化到
。此输出将生成空格作为分隔符。我可以把它改成一个真正的制表符吗?@N\u 2如果你有gnu sed,你可以使用
sed的| \([^:]*\):\(.*)|\2\t文件:///\1 |'文件
如果你想要制表符分离,但它不会像列输出那样漂亮