我有一些脚本名称及其路径存储在文本文件中。文本文件包含类似的路径
/myhome/new1/myfiles/test2.sh
/myhome/new3/myfiles/test1.sh
/myhome/new2/myfiles/test4.sh
/myhome/new/myfiles/test5.sh
这些 shell 文件正在被一些主脚本调用
我想要走该路径,主要路径存在于路径中(我不知道如何获取路径,无法 sed 最后一个分隔符)
我想 grep 文件名(以获取文件名使用
sed 's/.*\///' new.txt
)并存储shell 类型的文件名脚本写入文本文件。
输出在文本文件应该类似于路径、脚本名称和主脚本名称
/myhome/new1/myfiles/test2.sh test2 test2main.sh
/myhome/new3/myfiles/test1.sh test1 test1foo.sh
/myhome/new2/myfiles/test4.sh test4 test4bar.sh
/myhome/new/myfiles/test5.sh test5 baz5main.sh
test2main.sh
, test1foo.sh
, testo4bar.sh
... 是调用这些文件的主要脚本。
答案1
您可以使用以下脚本来实现此目的。从您的问题来看,尚不清楚您如何准确确定每个输入文件的“主”文件。在下面的脚本中,简单地假设它是文件夹中唯一的其他文件。
#!/usr/bin/env bash
while IFS= read -r f # every line is represented by $f
do
d=$(dirname "$f") # $f's directory
b=$(basename "$f") # $f's basename
bwoe=${b%.*} # $f's basename without extension
m=$(find "$d" -mindepth 1 -maxdepth 1 -not -name "$b" | head -n 1) # get first file in the folder that is not $f
m=$(basename "$m") # basename of main file
printf "%s\\t%s\\t%s\\n" "$f" "$bwoe" "$m"
done < input.txt # input.txt contains the input scripts
例子:
$ ls a b c
a:
afoo.sh a.sh
b:
bmain.sh b.sh
c:
c.sh cxx.sh
$ cat input.txt
a/a.sh
b/b.sh
c/c.sh
$ bash script.sh
a/a.sh a afoo.sh
b/b.sh b bmain.sh
c/c.sh c cxx.sh
答案2
如果我理解正确(请参阅评论),该命令的 GNUsed
标志e
可以s
帮助您使其成为单行代码(未经测试,抱歉):
sed -E 'h;s_(.*/)(.*)_grep -l \2 \1*.sh_e;x;G;s_([^/]*).sh\n_\1.sh \1 _' scriptfile
h
将线路保存在保留空间中,以便我们稍后在搞乱后可以恢复它s_.*/_grep -l \2 \1*.sh_e
真正的技巧是:.*/
匹配最后一个斜杠之前的所有内容,因此\1
将是路径,而\2
将是该行的其余部分(脚本名称)。 Nowgrep -l
插入到脚本名称之前和路径之前;这样/my/path/foo.sh
就变成了grep -l foo.sh /my/path/*.sh
。该标志在 shell 中执行此模式,因此它被包含的文件e
列表替换(希望只有一个,否则需要调整脚本)*.sh
/my/path
foo.sh
- 其余的很简单:
x
更改两个缓冲区并将保留缓冲区(现在带有 shell 的答案)附加到模式 s_([^/]*).sh\n_\1.sh \1 _
进行清理,复制脚本名称(不带.sh
)并删除换行符,因此您应该获得所需的输出
答案3
这里c-shell
可以成为真正的救世主:
% foreach line ( "`cat ./input.txt`" )
printf '%s\t%s\t' ${line:q} ${line:r:t:q}
printf '%smain\n' ${line:r:t:q}
end
其他方法有:
$ perl -F/ -pale '
my($t) = $F[-1] =~ /([^.]+)/;
$_ = join "\t", $_, $t, "${t}main" if /\S/;
' ./input.txt
$ sed -Ee '
s|([^/.]+)\.[^/.]+$|&\t\1\t\1main|;t
s|([^.]+)\.[^.]+$|&\t\1\t\1main|;t
s|([^/]+)$|&\t\1\t\1main|
' ./input.txt
结果:
/myhome/new1/myfiles/test2.sh test2 test2main
/myhome/new3/myfiles/test1.sh test1 test1main
/myhome/new2/myfiles/test4.sh test4 test4main
/myhome/new/myfiles/test5.sh test5 test5main
笔记:
o We have to be verbose as we need to cover the various possible cases that may arise.
o GNU sed is needed.
答案4
您可以使用 sed 中的捕获组和扩展正则表达式(-r 选项)来获取文件名并在最终输出中将原始字符串与脚本一起替换:
sed -r 's/(^.*\/)([^.]*)(.*$)/\1\2\3 \2 \2main/' test.txt
(^.*\/) -- 1st Capture, the path
([^.]*) -- 2nd Capture, the file up to the dot
(.*$) -- 3rd Capture, the file suffix