Shell 如何使用sed解析和修改查找结果?
我偶然发现了以下问题:在一行上,我想更改Shell 如何使用sed解析和修改查找结果?,shell,command-line,sed,find,ksh,Shell,Command Line,Sed,Find,Ksh,我偶然发现了以下问题:在一行上,我想更改find命令的结果,根据我找到的文件执行特定的cp,目标名称取决于find返回的文件 这是我的档案 $ find jcho -name *.data jcho/category1/001.data jcho/category2/002.data 它们必须复制到 jcho2/category1_001.data jcho2/category2_002.data 我试过这个 $ find . -name *.data \ -exec cp {} ` e
find
命令的结果,根据我找到的文件执行特定的cp
,目标名称取决于find
返回的文件
这是我的档案
$ find jcho -name *.data
jcho/category1/001.data
jcho/category2/002.data
它们必须复制到
jcho2/category1_001.data
jcho2/category2_002.data
我试过这个
$ find . -name *.data \
-exec cp {} ` echo {} | sed -re 's/(jcho\/)(category[0-9]*)(\/)(.*data)/jcho2\/\2_\4/' ` \;
但它说它想复制到同一个文件中——我的替换没有进行;出现以下错误:
cp:“./jcho/category1/001.data”和“./jcho/category1/001.data”是
同一文件
因此,我尝试了一种带有子shell的方法,并将结果提供给它。
这(有点)奏效了
==>
如果我能在sed
模式中包含/
,我的解决方案就在眼前。。。
但我得到:
find jcho -name *.data -exec sh -c \
'f="${0}"; d=$(echo ${f} | sed -re 's/(jcho\/)(category[0-9]*)(\/)(.*data)/jcho2\/\2_\4/' ); cp ${f} ${d} ' {} \;
-ksh:语法错误:`('意外
…我试着用\
逃离/
,用\
逃离\
…没有更好
等同于
find jcho -name *.data -exec sh -c \
'f="${0}"; d=$(echo ${f} | sed -re 's~\([^)]*\)/\([^()]*\)$~\1_\2~' ); cp ${f} ${d} ' {} \;
谢谢您的帮助!您可以将此
sed
与另一个分隔符~
一起使用:
find jcho -name '*.data' |
while read -r f; do cp "$f" "$(echo "$f" | sed 's~\([^)]*\)/\([^()]*\)$~\1_\2~')"; done
通过查找
输出,它将给出:
jcho/category1_001.data
jcho/category2_002.data
(和)需要转义,以便以后引用
必须使用正则表达式模式中的[/]或替换零件中的\/对/进行转义
您可以尝试下面的命令行:
$ find jcho -name \*.data | sed -n '
{
h
s/^\(.*\)[/]\(category[^/]*\)[/]\(.*[.]data\)$/\12\/\2_\3/
H
x
s/\n/ /
p
}' | xargs -L 1 cp
这适用于提供的示例,但如果路径名或文件名包含特殊字符:\n“”空格,则会出现问题
以下是关于这些主题的著名页面:
pattern buffer = jcho/category1/001.data
hold buffer = jcho/category1/001.data
2-h用模式缓冲区的副本覆盖保持缓冲区的内容
pattern buffer = jcho/category1/001.data
hold buffer = jcho/category1/001.data
3-第一个s更改模式缓冲区的内容
pattern buffer = jcho2/category1_001.data
4-H添加模式缓冲区以保持缓冲区
hold buffer = jcho/category1/001.data
jcho2/category1_001.data
5-x交换缓冲区内容
pattern buffer = jcho/category1/001.data
jcho2/category1_001.data
6-最后一个s命令将模式缓冲区中的“\n”替换为“”
pattern buffer = jcho/category1/001.data jcho2/category1_001.data
7-p打印当前图案缓冲区
pattern buffer = jcho/category1/001.data
hold buffer = jcho/category1/001.data
8-块结束:返回到1并使用找到的下一个文件名。可能有比这更简单的方法,但是使用bash basename/dirname组合可以实现同样的效果
for f in $(find ...); do cp $f $(echo $(dirname $f)"_"$(basename $f)); done
使用正则表达式匹配进行字符串操作。这与使用正则表达式模式和文件名替换使用
cp
[link]()检查那里的答案。不,它更具体。我尝试了不同的回答,但无法。我的问题向SED提出解决方案谢谢,但我仍然得到-ksh:语法错误:
)“意外的`为什么ksh
?您将问题标记为bash
,并且应该只使用bash
。很抱歉,我重新标记了它。sed
在bash
或ksh
中保持不变,所以这是另外一个问题。您能告诉我您正在尝试的是什么命令吗?谢谢Jay,但我正在尝试使用sed
带下标的方式-没有循环。@J.Chomel答案已经更新。让我知道你的评论。这对我很有效,谢谢。我想我在sed和理解h
,h
,x
,p
方面会有困难。@J.Chomel答案已经更新,请参阅底部的新章节。字母已被描述。我尝试了这种方法,但dirname
不是正确的目的地。这是我要复制到的另一个路径:jcho2
。