我有一台装有 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]
。