Linux Perl oneliner将路径中的确切单词与许多具有特殊字符的不同值进行匹配
如何精确匹配find/tmp-type l-exec ls-l输出中的$TARGET_NAME值Linux Perl oneliner将路径中的确切单词与许多具有特殊字符的不同值进行匹配,linux,perl,bash,ksh,ls,Linux,Perl,Bash,Ksh,Ls,如何精确匹配find/tmp-type l-exec ls-l输出中的$TARGET_NAME值 $ find /tmp -type l -exec ls -l 2>/dev/null {} + lrwxrwxrwx 1 root root 24 Mar 18 12:41 /tmp/test/link -> /usr/admin/Collect_tests lrwxrwxrwx 1 root root 43 Mar 18 12:41 /tmp/test/link1 ->
$ find /tmp -type l -exec ls -l 2>/dev/null {} +
lrwxrwxrwx 1 root root 24 Mar 18 12:41 /tmp/test/link -> /usr/admin/Collect_tests
lrwxrwxrwx 1 root root 43 Mar 18 12:41 /tmp/test/link1 -> /usr/admin/Collect_tests/Upload.CM@.www.com
lrwxrwxrwx 1 root root 68 Mar 18 12:41 /tmp/test/link2 -> /usr/admin/Collect_tests/Upload.CM@.www.com/Upload_Shema@@@.DATA.com
lrwxrwxrwx 1 root root 100 Mar 18 12:42 /tmp/test/link3 -> /usr/admin/Collect_tests/Upload.CM@.www.com/Upload_Shema@@@.DATA.com/List.files.emails.dummy*Printed
lrwxrwxrwx 1 root root 92 Mar 18 12:42 /tmp/test/link4 -> /usr/admin/Collect_tests/Upload.CM@.www.com/Upload_Shema@@@.DATA.com/List.files@emails.dummy
价值实例
TARGET_NAME=Upload.CM@.www.com
TARGET_NAME=Upload_Shema@@@.DATA.com
TARGET_NAME=List.files.emails.dummy*Printed
目标:仅当$Target\u name
精确匹配最后一个字段中的单词
示例(当我们希望精确匹配-whileTARGET\u NAME=Upload\u Shema@@@DATA.com时)
然后):
结果将显示如下所示
/tmp/test/link2 /usr/admin/Collect_tests/Upload.CM@.www.com/Upload_Shema@@@.DATA.com
/tmp/test/link3 /usr/admin/Collect_tests/Upload.CM@.www.com/Upload_Shema@@@.DATA.com/List.files.emails.dummy*Printed
/tmp/test/link4 /usr/admin/Collect_tests/Upload.CM@.www.com/Upload_Shema@@@.DATA.com/List.files@emails.dummy
有几个条件:
1) 只需匹配最后一个字段(从ls-l
output)
范例
/usr/admin/Collect_tests/Upload.CM@.www.com
2) $TARGET\u NAME值应与整个单词匹配
完全匹配的示例(而TARGET\u NAME=Upload)。CM@.www.com):
非完全匹配的示例:
/usr/admin/Collect_tests/Upload.CM@.www.c
3) 反斜杠(“/”)必须位于$TARGET\u NAME的左侧,反斜杠或字符串的结尾必须位于$TARGET\u NAME的右侧
4) 需要将特殊字符转义为:“/”、“@”。“*”等
5) 代码将是ksh脚本的一部分(可以由Perl oneliner或ksh等实现)
示例
find /tmp -type l -exec ls -l 2>/dev/null {} + | < Perl one liner .............. >
find/tmp-type l-exec ls-l 2>/dev/null{}+|
提供以下链接
$ cd /tmp
$ ls -l link* | sed -e 's/^.*\(link\)/\1/'
link -> /usr/admin/Collect_tests
link1 -> /usr/admin/Collect_tests/Upload.CM@.www.com
link2 -> /usr/admin/Collect_tests/Upload.CM@.www.com/Upload_Shema@@@.DATA.com
link3 -> /usr/admin/Collect_tests/Upload.CM@.www.com/Upload_Shema@@@.DATA.com/List.files.emails.dummy*Printed
link4 -> /usr/admin/Collect_tests/Upload.CM@.www.com/Upload_Shema@@@.DATA.com/List.files.emails.dummy
link5 -> /usr/admin/Collect_tests/Upload.CM@.www.com/
使用文件::查找模块,如中所示
$ TARGET_NAME='Upload_Shema@@@.DATA.com' perl -MFile::Find -le 'find sub {
-l && defined($dst = readlink $_) &&
index($dst, $ENV{TARGET_NAME}) >= 0 &&
print "$File::Find::name $dst" }, @ARGV' /tmp
/tmp/link2 /usr/admin/Collect_tests/Upload.CM@.www.com/Upload_Shema@@@.DATA.com
/tmp/link3 /usr/admin/Collect_tests/Upload.CM@.www.com/Upload_Shema@@@.DATA.com/List.files.emails.dummy*Printed
/tmp/link4 /usr/admin/Collect_tests/Upload.CM@.www.com/Upload_Shema@@@.DATA.com/List.files.emails.dummy
作为一艘客轮,那真是太笨拙了。作为一个单独的命令,它变为
#! /usr/bin/env perl
use strict;
use warnings;
use File::Find;
die "Usage: $0 root-dir ..\n" unless @ARGV;
die "$0: TARGET_NAME is not defined\n" unless exists $ENV{TARGET_NAME};
sub print_matching_target_name {
return unless -l && defined(my $dst = readlink $_);
print "$File::Find::name $dst\n" if index($dst, $ENV{TARGET_NAME}) >= 0;
}
find \&print_matching_target_name, @ARGV;
样本输出:
$ find-target
Usage: find-target root-dir ..
$ find-target /tmp
find-target: TARGET_NAME is not defined
$ TARGET_NAME=Upload.CM@.www.com ./find-target /tmp
/tmp/link2 /usr/admin/Collect_tests/Upload.CM@.www.com/Upload_Shema@@@.DATA.com
/tmp/link3 /usr/admin/Collect_tests/Upload.CM@.www.com/Upload_Shema@@@.DATA.com/List.files.emails.dummy*Printed
/tmp/link4 /usr/admin/Collect_tests/Upload.CM@.www.com/Upload_Shema@@@.DATA.com/List.files.emails.dummy
$find目标
用法:查找目标根目录。。
$find target/tmp
查找目标:未定义目标名称
$TARGET_NAME=上传。CM@.www.com/查找目标/tmp
/tmp/link2/usr/admin/Collect_测试/上传。CM@.www.com/上传_Shema@@@DATA.com
/tmp/link3/usr/admin/Collect_测试/上传。CM@.www.com/上传_Shema@@@DATA.com/List.files.emails.dummy*打印
/tmp/link4/usr/admin/Collect_测试/上传。CM@.www.com/上载_Shema@@@DATA.com/List.files.emails.dummy尝试执行以下操作:
#!/bin/bash
while IFS= read -r file; do
printf "TARGET_NAME=%q\n" "$file"
done < <(find /tmp -type l -printf '%l\n')
由于目标可能与要返回的部分相同,也可能不相同,因此似乎最容易进行两个单独的正则表达式调用(如果应该推广,也可能有帮助): 换句话说,找到目标短语,然后得到find的最后一个组件(不包含“/”的组件)。当两个条件都满足时,打印括号中捕获的文本 关于特殊字符:
如果将“#”替换为更传统的“/”,您需要避开我写的“/”,否则,“@”不会给您带来麻烦。当然,如果它在您的系统上运行,只需使用“\”对它们进行转义,正如您在回答上一个问题时提到的(自删除后),解析
ls
输出是非常不理想的<代码>读取链接可以改为使用
find /tmp -type l -exec \
perl -e'
my $TARGET_NAME = shift;
for (@ARGV) {
my $p = readlink($_);
$p =~ m{(?:^|/)\Q$TARGET_NAME\E(?:/|\z)}
or next;
print("$_\t$p\n");
}
' "$TARGET_NAME" {} \;
或者更有效地说
perl -MFile::Find::Rule -e'
my ($TARGET_NAME, $BASE) = @ARGV;
for (File::Find::Rule->symlink->in($BASE)) {
my $p = readlink($_);
$p =~ m{(?:^|/)\Q$TARGET_NAME\E(?:/|\z)}
or next;
print("$_\t$p\n");
}
' "$TARGET_NAME" /tmp
按照要求,这将匹配
TARGET_NAME
TARGET_NAME/
TARGET_NAME/x
.../TARGET_NAME
.../TARGET_NAME/
.../TARGET_NAME/x
但不是
TARGET_NAMEx/...
.../TARGET_NAMEx
.../TARGET_NAMEx/...
xTARGET_NAME/...
.../xTARGET_NAME
.../xTARGET_NAME/...
注意:更改
查找-执行官…\代码>到查找-执行+
如果您的find
支持它。?不要解析ls输出,即使它来自find
@Sputnick我没有其他选择(我需要验证链接指向的所有路径)是的,您可以举例说明:find-type l-printf“%l\n”
这是一个更好的开始。@Sputnick thx,这是我的新信息为什么不打印“TARGET\u NAME=%q\n'$file”
?另外,为什么要使用两个“-printf“%l\n”选项来find
?@Sputnick为什么在“*”之前打印“\”,输出应该与相应编辑的目录/文件名相同。删除了一个打字错误并添加了一个improvement@Eytan,这是为了满足以下要求:4)需要将特殊字符转义为:“/”、“@”。“*”,etc
请注意,如果链接目标包含任何字符(如嵌入换行符),则printf“%q”
的输出将包含类似bash的$'foo\nbar'
。这些要求没有规定如何处理这种情况。是否可以在“TARGET\u NAME”之前打印链接文件,例如:/tmp/link TARGET\u NAME=Upload。CM@.www.comany为什么我的问题的目标是验证$target_NAME值在路径(最后一个字段)中是否匹配,我不想只打印每个路径的基本名称-目标是将$target_名称与输出(最后一个字段路径)匹配@Eytan我知道您现在在寻找什么。参见更新的answer.thanx,还有一个问题如果我还想打印完整的$TARGET\u名称,我需要设置:print“$File::Find::NAME$b”$ENV{TARGET\u NAME},@ARGV'/tmp???我需要的示例:/tmp/test/link2 Upload\u Shema@@@DATA.com/usr/admin/Collect\u tests/Upload。CM@.www.com/上传_Shema@@@DATA.com(这句话和我告诉Olaf的话是一样的)如果我设置了TARGET_NAME=Collect_tests,那么我希望看到6行匹配的“查看我的查询详细信息”,所以…(对于所有链接,link1、link2、link3、link4、link5)代码仅打印链接收集测试备注-我希望打印与$TARGET\u名称匹配的所有行的原因,因为我以后需要重新创建新链接第二个问题代码无法在solaris 10上工作…无法理解此问题?(无任何代码输出)ug,你的帖子与你的第一条评论完全相反。我已经修正了你的问题,并相应地调整了我的答案。如果你不告诉我问题是什么,我就无法修正你的Solaris问题。(find
不会产生任何结果?@ARGV
empty?Regex不匹配?)你知道为什么你的第一个代码不适合solaris 10吗?(它只在linux上运行)
perl -MFile::Find::Rule -e'
my ($TARGET_NAME, $BASE) = @ARGV;
for (File::Find::Rule->symlink->in($BASE)) {
my $p = readlink($_);
$p =~ m{(?:^|/)\Q$TARGET_NAME\E(?:/|\z)}
or next;
print("$_\t$p\n");
}
' "$TARGET_NAME" /tmp
TARGET_NAME
TARGET_NAME/
TARGET_NAME/x
.../TARGET_NAME
.../TARGET_NAME/
.../TARGET_NAME/x
TARGET_NAMEx/...
.../TARGET_NAMEx
.../TARGET_NAMEx/...
xTARGET_NAME/...
.../xTARGET_NAME
.../xTARGET_NAME/...