列出文件名的特定部分及其内容

列出文件名的特定部分及其内容

我有一台装有 BusyBox 的 Linux 机器,其中有一个名为/data/var/lib/connman.该目录包含一些我不感兴趣的目录。但它包含许多具有类似“ wifi_<HASH1>_<HASH2>_managed_psk.config”的文件名模式的 .config 文件。我的示例中的文件名包含有趣的哈希部分 , <HASH1>_<HASH2>它们是字母数字字符。完整文件名的示例如下:

  • “wifi_ff001122334_567890123456_management_psk.config”
  • “wifi_778899ad_112233445566_management_none.config”

那么每个文件都是一个文本文件,如果它包含我感兴趣的行:

Name = <SSID>

有趣的是<SSID>

该行的真实示例是:

Name = MySSID
Name = r23$f"§F §"fsdfSdf

现在我想从文件名中获取所有哈希值及其值<SSID>, 像这样:

<HASH> : <SSID>

这就是我想要的输出:

MySSID : 01abcd89
MyOtherSSID : ff001122334455,
r23öf"§F§"fsdfSdf : 7876543ad

所以我们需要从文件名中获取哈希部分,同时查看“Name =”后面的文件内容。

我尝试过 grep 和 awk 的组合,但从未得到所需的输出。

我可以使用什么命令来实现这一目标?

答案1

使用(以前称为 Perl_6)

~$ raku -e 'for dir(test => / \.config $/ ) -> $fh {
                put join " : ",
                    $_.split(/ \s* \= \s* /)[1],
                    $fh.match(/ <?after wifi_ > .*? <?before _managed > /)
                for $fh.lines.grep(/^Name/)
             };'

该解决方案使用 Raku,Perl 编程语言家族的成员。上面的代码依赖于 Rakudir()grep()例程,因此在经典 shell 介导的文件通配不存在/受限的平台上可能很有用(请参阅 SO 讨论)这里)。

简而言之,raku 是用 -e 选项调用的,它告诉 Raku 的编译器 (Rakudo) 编译并执行给定的单行程序。dir()使用关键字调用该方法for,该关键字告诉 Raku 循环使用过滤器获得的文件名值test => / \.config $/。各个结果文件名被分配给临时变量$fh并在块内迭代。

  • 一旦进入块(从右到左读取),$fh.lines.grep(/^Name/)每个文件句柄都会逐行分析是否存在以文本“Name”开头的行。如果找到,Raku 会自动将该行分配给$_主题变量,然后按空格/等号拆分,并.[1]隔离第二个元素(SSID 值)。

  • 文件$fh名也被调整为最终格式,在文本“wifi_”之后和文本“_management”之前隔离.*?零个或多个字符。<?after wifi_ ><?before _managed >

  • 结果输出按请求的空格/冒号进行编辑put,首先是文件名片段,后跟 SSID 值。join:

输入示例(密码):

~$ ls *.config
wifi_778899ad_112233445566_managed_none.config      wifi_ff001122334_567890123456_managed_psk.config

~$ cat wifi_778899ad_112233445566_managed_none.config
Name : SSIDabcd
junk
Name : SSIDefgh

~$ cat wifi_ff001122334_567890123456_managed_psk.config
Name : SSID1234
junk
Name : SSID5678

示例输出:

SSIDabcd : 778899ad_112233445566
SSIDefgh : 778899ad_112233445566
SSID1234 : ff001122334_567890123456
SSID5678 : ff001122334_567890123456

请注意,隔离上面的文件名文本片段match依赖于 Raku 的新前瞻/后瞻习惯用法。如果您更愿意使用 Raku 的<(…… )>“捕获标记”,则match可以将该操作改为:

$fh.match(/ wifi_ <( .*? )> _managed /)

https://docs.raku.org/routine/dir
https://docs.raku.org/routine/grep
https://raku.org

答案2

由于系统使用的是busybox,我认为它不会有perl之类的东西。 busybox 有一个非常强大的awk实现,所以你应该能够做到:

find . -name '*_*_*_*.config' -type f -exec awk '
  match($0, /^[[:blank:]]*Name[[:blank:]]*=[[:blank:]]*[^[:blank:]]/) {
    ssid = substr($0, RLENGTH)
    sub(/[[:blank:]]+$/, "", ssid)
    base = FILENAME
    sub(".*/", "", base)
    if (match(base, "_[[:xdigit:]]+_[[:xdigit:]]+_"))
      print ssid, substr(base, RSTART+1, RLENGTH-2)
    nextfile
  }' {} +

如果你的 busybox 是在不支持 的情况下构建的find -exec {} +,你可以用 替换,+但这';'只会降低效率。

如果它是在不支持 POSIX 字符类的情况下构建的awk,则可以[[:blank:]][ \t][[:xdigit:]]替换[0-9a-fA-F]

相关内容