【问题标题】:grep only specific section of file; determine OS X system version in a shell script仅 grep 文件的特定部分;在 shell 脚本中确定 OS X 系统版本
【发布时间】:2013-12-08 11:25:04
【问题描述】:

要查找用户正在运行的 OS X 的当前版本,SystemVersion.plist 文件将显示此内容。如何使用grep 命令仅查找版本号并返回它?

例如:

cat /System/Library/CoreServices/SystemVersion.plist

将产生:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
 <dict>
    <key>ProductBuildVersion</key>
    <string>13A598</string>
    <key>ProductCopyright</key>
    <string>1983-2013 Apple Inc.</string>
    <key>ProductName</key>
    <string>Mac OS X</string>
    <key>ProductUserVisibleVersion</key>
    <string>10.9</string>
    <key>ProductVersion</key>
    <string>10.9</string>
</dict>
</plist>

所以,在适当的时候我会运行:

cat /System/Library/CoreServices/SystemVersion.plist | grep 10.9

这会返回:

    <string>10.9</string>
    <string>10.9</string>

第二个&lt;string&gt;10.9&lt;/string&gt; 来自&lt;key&gt;ProductUserVisibleVersion&lt;/key&gt; 键。我将如何操作 grep 命令以便它搜索并 ONLY 从这里返回 10.9 only?我知道我在示例中使用了grep 来专门查找10.9 响应,但我想显示&lt;string&gt;&lt;/string&gt; 之间出现的任何内容。

我将把它合并到一个测试中,希望返回 visible OS X 版本并使用 if / else 命令检查它,然后相应地运行调用函数.

我对@9​​87654331@ 脚本解决方案持开放态度,因为我也可以将其实施到其他选项中。 AppleScript 作为替代解决方案也很值得了解。

【问题讨论】:

  • @DigiMonk 我结合使用 AppleScript 和 bash 来完成某些任务。 Bash 是我主要追求的,我首先用“bash”和“grep”标记了这个问题,后来我添加了“AppleScript”。

标签: string macos bash grep applescript


【解决方案1】:

我会使用xml 解析器。这里有一个 及其XML::Twig 模块的示例:

#!/usr/bin/env perl

use warnings;
use strict;
use XML::Twig;

XML::Twig->new(
    twig_handlers => {
        'plist/dict/string' => sub {
            my $prev = $_->prev_sibling('key');
            return unless defined $prev;
            if ( $prev->tag eq 'key' and 
                 $prev->text_only eq 'ProductUserVisibleVersion' ) {
                printf "%s\n", $_->text_only;
                exit 0;
            }   
        },  
    },  
)->parsefile( shift );

你可以像这样运行它:

perl script.pl /System/Library/CoreServices/SystemVersion.plist

产生:

10.9

【讨论】:

  • 我从未使用过 Perl,因为我不知道如何使用。我将把这个答案收起来以备后用,因为当我将来某个时候深入研究 Perl 时它可能会派上用场。谢谢。
【解决方案2】:

以下内容并未解决一般的 grep 相关问题,但简洁地解决了您的具体问题:

/usr/libexec/PlistBuddy -c 'print :ProductUserVisibleVersion' /System/Library/CoreServices/SystemVersion.plist

基于 AppleScript 的替代解决方案:

osascript -e 'system version of (system info)'

【讨论】:

  • 我将正确答案授予您,不是因为@DigiMonk 所说的,而是因为您已经成功地回答了applescriptbash 两个选项。我从问这个问题中得到了很多启示
  • 谢谢@DanijelJ(不过你还没有接受它)。由于现在的答案为获取 OS X 版本 有用的通用解析技术提供了简单的解决方案,您是否介意修改问题标题以反映这一点(也许在问题正文中添加一点前言)?
【解决方案3】:

Apple 正在逐渐将他们在 OS X 中的 plist 文件从 XML 转换为二进制格式,所以我建议使用知道如何读取两者的东西:defaultsPlistBuddy

$ defaults read /System/Library/CoreServices/SystemVersion ProductUserVisibleVersion
10.8.5
$ /usr/libexec/PlistBuddy -c "print :ProductUserVisibleVersion" /System/Library/CoreServices/SystemVersion.plist 
10.8.5

(显然,我运行的是 10.8.5,但相同的命令应该适用于 10.9 或 10.7,或者...)

【讨论】:

    【解决方案4】:

    我会使用 grep 和 sed:

    $ grep -e "<string>[0-9]+\.[0-9]+</string>" | sed -n -e 's/([0-9]+\.[0-9]+)/\1/p'
    

    我还没有测试过,但它是类似的!

    【讨论】:

    • 感谢您向我展示了使用 sed 的示例。我试图自己做这件事,但惨遭失败。我将能够保留这个示例,并在以后的项目中以它为基础。
    【解决方案5】:

    简单的方法。

    awk '/ProductUserVisibleVersion/ {getline;print}' /System/Library/CoreServices/SystemVersion.plist
    <string>10.9</string>
    

    或者只是价值

    awk -F"<|>" '/ProductUserVisibleVersion/ {getline;print $3}' /System/Library/CoreServices/SystemVersion.plist
    10.9
    

    【讨论】:

    • 这是一个被低估的答案。我试图为 Info.plist 找到类似的答案。虽然这将是一个非常明显的事情,因为 plist 在 iOS / macOS 开发中如此常用,所以到处都回答/解释了很多次。但是您的答案是第一个精确有用的“shell”答案(并且不使用 PlistBuddy 或仅使用 macOS #$*&^ 的任何东西)。谢谢。
    • @SwapnilLuktuke 这是一个旧答案。因为我后来发现getline 充满了陷阱,应该避免,你可以改用它。 awk -F"&lt;|&gt;" 'f {print $3;f=0} /ProductUserVisibleVersion/ {f=1}' filename 它将搜索文本,如果找到则设置标志 f。如果标志 f 为真(下一行),则打印值并将标志 f 设置为 0。
    • 谢谢。您可以使用此更新编辑您的答案。
    【解决方案6】:

    100% 外部 Bash:

    grep -A2  '<key>ProductUserVisibleVersion</key>' | grep '<string>' |cut -d\> -f2 |cut -d\< -f1
    

    或 100% 内部 Bash:

    while read LINE
    do
        if [ "$LINE" = "<key>ProductUserVisibleVersion</key>" ]
        then   
            read LINE
            LINE=${LINE#*>}
            echo ${LINE%<*}
            exit
        fi
    done
    

    【讨论】:

      猜你喜欢
      • 2019-08-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-17
      相关资源
      最近更新 更多