如何“ for f循环”并删除空白行

时间:2019-04-23 20:44:59

标签: bash

我正在连接到macOSX Shell,并运行bash命令来扫描info.plist并打印结果,但是,我得到了一些空白行

for f in $(find . -name 'Info.plist'); do grep -A 1 -e CFBundleIdentifier -e CFBundleVersion $f 2>/dev/null | awk -F "[<>]" '{print $3}'; done
for f in $(find . -name 'Info.plist'); do grep -A 1 -E 'CFBundleIdentifier|CFBundleVersion' $f 2>/dev/null | awk -F "[<>]" '{print $3}'; done

结果:

CFBundleIdentifier
com.apple.xcode.dsym.com.app.app1

CFBundleVersion
2.16.0.4386
CFBundleIdentifier
com.apple.xcode.dsym.app.app1Additions

CFBundleVersion
1

问题似乎出在Grep -e或-E上。如果我只做一个grep并使用-A 1打印下一行,我将没有任何空格

没有多次抱怨的结果:

for f in $(find . -name 'Info.plist'); do grep -A 1 CFBundleIdentifier $f 2>/dev/null | awk -F "[<>]" '{print $3}'; done

结果:

CFBundleIdentifier
com.apple.xcode.dsym.com.app.app1
CFBundleIdentifier
com.apple.xcode.dsym.app.app1Additions

我如何更好地扫描info.plist并打印CFBundleIdentifier +下一行和CFBundleIdentifier +下一行并得到结果

  1. 没有空间
  2. 每个info.plist后的空格

预期结果:

CFBundleIdentifier
com.apple.xcode.dsym.com.app.app1
CFBundleVersion
2.16.0.4386
<Actual real space>
CFBundleIdentifier
com.apple.xcode.dsym.app.app1Additions
CFBundleVersion
1

更新1:

添加完整的Info.plist进行审核

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" 
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>CFBundleDevelopmentRegion</key>
    <string>English</string>
    <key>CFBundleIdentifier</key>
    <string>com.apple.xcode.dsym.com.app.app1/string>
    <key>CFBundleInfoDictionaryVersion</key>
    <string>6.0</string>
    <key>CFBundlePackageType</key>
    <string>dSYM</string>
    <key>CFBundleSignature</key>
    <string>????</string>
    <key>CFBundleShortVersionString</key>
    <string>2.16.0</string>
    <key>CFBundleVersion</key>
    <string>2.16.0.4385</string>
</dict>

3 个答案:

答案 0 :(得分:1)

我怀疑根本问题是某些Info.plist文件采用的是属性列表格式的二进制形式,而不是XML形式,因此grep会打印出如下几行:

Binary file ./some/path/to/Info.plist matches

...,然后awk尝试打印第三个字段(某种),但那里没有任何相关内容。

为了解决此问题,您需要停止使用grepawk,并使用一种能够真正理解属性列表格式(所有形式)的工具,例如defaultsPlistBuddydefaults在如何指定文件路径方面存在一些问题,因此我投票赞成PlistBuddy

此外,正如@chepner和@EdMorton指出的那样,在for的输出上进行find循环并不是处理文件名的安全方法,尤其是在macOS中,文件名中的空格很常见。 PlistBuddy将很容易直接与find ... -exec一起使用,但是由于您希望在每个文件后留一个空白行,因此更加复杂。可能最简单的方法是使用while read循环(使用以空分隔的文件名来避免空格等问题):

find . -name 'Info.plist' -print0 |
    while IFS= read -r -d '' file; do
        /usr/libexec/PlistBuddy -c "print CFBundleIdentifier" -c "print :CFBundleVersion" "$file" 2>/dev/null
        echo
    done

请注意,这不会打印“ CFBundleIdentifier”和“ CFBundleVersion”行,而仅打印那些属性列表元素中的数据。如果要使用这些名称,则又要复杂一点,因为您必须测试plist中是否确实存在这些项目。

答案 1 :(得分:0)

空白行来自第三字段中没有任何内容的行。因此,请在awk中进行检查。

for f in $(find . -name 'Info.plist'); do 
    grep -A 1 -E 'CFBundleIdentifier|CFBundleVersion' $f 2>/dev/null | 
        awk -F "[<>]" '$NF >= 3 {print $3}'
done

答案 2 :(得分:0)

您没有提供任何示例输入,因此这只是一个猜测,但您似乎只是想查找几个字符串,然后从包含该字符串的行及其后的行打印第三个字段。如果是这样,那就是:

find . -name 'Info.plist' -exec \
    awk -F'[<>]' '/CFBundle(Identifier|Version)/{c=2} c&&c--{print $3}' {} +

如果您的find不支持将+作为参数,请改用\;

您可能想阅读https://unix.stackexchange.com/q/169716/133219https://mywiki.wooledge.org/Quoteshttp://mywiki.wooledge.org/DontReadLinesWithFor,因为它们解决了脚本中的其他一些问题。