AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / computer / 问题 / 1616298
Accepted
Phil
Phil
Asked: 2021-01-10 11:54:58 +0800 CST2021-01-10 11:54:58 +0800 CST 2021-01-10 11:54:58 +0800 CST

如何从 shortcuts.vdf 文件中提取我在 Steam 中添加了快捷方式的游戏名称?

  • 772

我正在尝试整理一个 Excel 表格,其中列出了我已将快捷方式添加到 Steam 的所有游戏。Steam 允许您为非 Steam 游戏添加快捷方式并充当它们的启动器。用户添加的快捷方式链接位于名为 shortcuts.vdf 的本地数据库中,其中包含与 Steam 拥有的游戏相关的所有信息。我基本上感兴趣的是游戏的名称。

这是文件中的数据在记事本中的样子的片段:

shortcuts  0 appid °rõÄappname Cemu Exe "T:\Cemu\App+Update+DLC\Cemu.exe" StartDir "T:\Cemu\App+Update+DLC\" icon  ShortcutPath  LaunchOptions  IsHidden     AllowDesktopConfig    AllowOverlay    openvr     Devkit     DevkitGameID  LastPlayTime ZùÏ_ tags 0 favorite 1 All Games  1 appid }yâappname Citra Nightly Exe "C:\Users\phili\AppData\Local\Citra\nightly-mingw\citra-qt.exe" StartDir "C:\Users\phili\AppData\Local\Citra\nightly-mingw\" icon  ShortcutPath  LaunchOptions  IsHidden     AllowDesktopConfig    AllowOverlay    openvr     Devkit     DevkitGameID  LastPlayTime ¿
ã_ tags 0 favorite 1 All Games  2 appid {Sü¸appname RollerCoaster Tycoon 2: Triple Thrill Pack Open Exe "C:\Program Files\OpenRCT2\openrct2.exe" StartDir "C:\Program Files\OpenRCT2\" icon  ShortcutPath  LaunchOptions  IsHidden     AllowDesktopConfig    AllowOverlay    openvr     Devkit     DevkitGameID  LastPlayTime !Ý_ tags 0 steam 1 All Games  3 appid Iì»Âappname Art Of Fighting 2 Exe "R:\Amazon Games\Library\Art of Fighting 2\ArtOfFighting2.exe" StartDir "R:\Amazon Games\Library\Art of Fighting 2\" icon  ShortcutPath  LaunchOptions  IsHidden     AllowDesktopConfig    AllowOverlay    openvr     Devkit     DevkitGameID  LastPlayTime      tags 0 Shortcuts 1 Amazon 2 All Games  4 appid ñappname Origin Exe "C:\Program Files (x86)\Origin\Origin.exe" StartDir "C:\Program Files (x86)\Origin\" icon  ShortcutPath  LaunchOptions  IsHidden     AllowDesktopConfig    AllowOverlay    openvr     Devkit     DevkitGameID  LastPlayTime ÛÊ*] tags 0 steam 1 All Games  5 appid £á@¤appname A Good Snowman Is Hard To Build Exe "R:\Amazon Games\Library\A Good Snowman Is Hard To Build\Snowman.exe" StartDir "R:\Amazon Games\Library\A Good Snowman Is Hard To Build\" icon  ShortcutPath  LaunchOptions  IsHidden     AllowDesktopConfig    AllowOverlay    openvr     Devkit     DevkitGameID  LastPlayTime      tags 0 Shortcuts 1 Amazon 2 All Games  6 appid ¢‡    æappname Adam Wolfe Exe "R:\Amazon Games\Library\Adam Wolfe\AdamWolfe.exe" StartDir "R:\Amazon

我注意到我添加到 Steam 的游戏名称总是在单词appnameand之间Exe,如下所示:

£á@¤appname A Good Snowman Is Hard To Build Exe

如何从该文件中修改/提取条目,以便我有一个 Excel 表,其中包含每行一个单元格之间appname的条目?Exe

像这样:

excel表格中的条目列表

我可能在考虑正则表达式?我没有 Microsoft Office,只有 Libre Office

原shortcuts.vdf文件上传+txt转换版本。

microsoft-excel regex
  • 3 3 个回答
  • 957 Views

3 个回答

  • Voted
  1. Richard
    2021-01-12T09:00:28+08:002021-01-12T09:00:28+08:00

    Here is a very hacky bit of vbscript which essentially breaks down the shortcuts.vdf file into seperate lines (based on the nul character) and then spits out the next line after the one called AppName. I did try to just split file using Chr(0) as the delimiter but it threw an error .

    Save the following file as steam.vbs:

    Dim oFile: Set oFile = CreateObject("Scripting.FileSystemObject").GetFile("shortcuts.vdf")
    Dim file : file = oFile.OpenAsTextStream().Read(oFile.Size)
    
    Dim content, i, c
    
    For i = 1 To Len(file)
        c = Asc(Mid(file, i, 1))
        If c = 0 Then 
            content = content & VbCrLf
        ElseIf c > 3 Then
            content = content & Chr(c)
        end If
    Next
    
    Dim items : items = Split(content, VbCrLf)
    
    For i = 0 To Ubound(items)
        If Instr(LCase(items(i)), "appname") > 0 Then Wscript.Echo items(i+1)
    Next
    
    Set oFile = Nothing
    

    Copy the shortcuts.vcf file into the same folder as this code and then from a command line type:

    cscript steam.vbs > output.txt
    

    在任何文本编辑器中打开输出,您将看到您添加的所有游戏快捷方式的列表。

    • 4
  2. Best Answer
    Ξένη Γήινος
    2021-01-10T19:44:46+08:002021-01-10T19:44:46+08:00

    这应该很容易实现,您只需要 PowerShell,不需要 Office 套件。

    从路径的语法来看,它们以驱动器号(即 T:) 开头并使用反斜杠 ( \) 分隔目录,我假设您在 Windows 上。

    您在 Windows 上,使用它打开 PowerShell:

    Win+ R→类型PowerShell→ Ctrl+ Shift+Enter

    然后,一旦你在 PowerShell 中,你可以使用这个正则表达式来获取游戏名称:(appname)(.*?)(Exe)

    Steam .vdf 格式是一种专有格式,因此很难正确解析该格式,尽管您可能可以使用此:GitHub:Steam-GetOnTop,我不使用 Steam,也没有使用该包,所以我不保证它会起作用。

    但是由于文件是明文编码的,可以用notepad.exe打开,只需要和之间的内容appname,Exe可以使用蛮力的方式:

    $shortcuts=((Get-Content "C:\Program Files (x86)\Steam\userdata\149576161\config\shortcuts.vdf").ToCharArray() | where{![char]::IsControl("$_")}) -join ""
    ($shortcuts | Select-String -pattern "(appname)(.*?)(Exe)" -AllMatches).matches.value | %{$_.Substring(7,$_.Length-10)} | sort-object | out-file "$([environment]::getfolderpath('desktop'))\gamename.txt"
    

    解释:

    第一步:我们获取shortcuts.vdf的内容,将字符串转换为字符数组,过滤掉Control Characters,加入字符串

    步骤 2:我们打印我们在第一步中获得的内容并将其传递到管道中;我们从管道中获取内容并选择所有匹配的字符串(appname)(.*?)(Exe),并用于().matches.value仅获取匹配项,然后我们将其删除appname并将Exe其导出到位于您桌面上的名为 gamename.txt 的文件中。

    但是,如果您坚持要导出到只有一列的 Excel 工作表,请使用以下命令:

    $shortcuts=((Get-Content "C:\Program Files (x86)\Steam\userdata\149576161\config\shortcuts.vdf").ToCharArray() | where{![char]::IsControl("$_")}) -join ""
    ($shortcuts | Select-String -pattern "(appname)(.*?)(Exe)" -AllMatches).matches.value | %{$_.Substring(7,$_.Length-10)} | sort-object | %{[PSCustomObject]@{GameName=$_}} | export-csv "$([environment]::getfolderpath('desktop'))\gamename.csv"
    

    该方法与第一种方法几乎相同,但我们将结果转换为[PSCustomObject]并将最终结果导出到位于路径“C:\Users\USERNAME\Desktop\gamename.csv”的 .csv 文件,而不是 .txt 文件.


    进一步说明:

    Microsoft Docs:什么是 PowerShell?

    Microsoft Docs:关于变量

    Microsoft Docs:关于 Foreach

    Microsoft Docs:关于 PSCustomObject 你想知道的一切

    Microsoft Docs:关于数组你想知道的一切

    Microsoft Docs:关于数组

    Microsoft Docs:获取内容

    Microsoft Docs:选择字符串

    Microsoft Docs:Out-File

    Microsoft Docs:导出-CSV


    输出

    正如您所说,它不包含任何个人信息并将文件附加到问题中,我将在下面发布我得到的结果:

    Google Drive

    我的第一种方法的输出:

    游戏名.txt

    在此处输入图像描述

    我的第二种方法的输出:

    游戏名.csv

    在此处输入图像描述

    从另一个答案输出 vbs 方法:

    蒸汽.txt

    在此处输入图像描述


    代码效率分析

    第一种方法是 358 个字符长

    第二种方法是396个字符长

    vbs 脚本长度为 541 个字符

    第一种方法打高尔夫球:

    $s=((gc "C:\Program Files (x86)\Steam\userdata\149576161\config\shortcuts.vdf").ToCharArray() | ?{![char]::IsControl("$_")}) -join ""
    ($s | sls "(appname)(.*?)(Exe)" -all).matches.value | %{$_.Substring(7,$_.Length-10)} | sort >"$([environment]::getfolderpath('desktop'))\gamename.txt"
    

    286 个字符长

    第二种方法打高尔夫球:

    $s=((gc "C:\Program Files (x86)\Steam\userdata\149576161\config\shortcuts.vdf").ToCharArray() | ?{![char]::IsControl("$_")}) -join ""
    ($s | sls "(appname)(.*?)(Exe)" -all).matches.value | %{$_.Substring(7,$_.Length-10)} | sort | %{[PSCustomObject]@{GameName=$_}} | epcsv "$([environment]::getfolderpath('desktop'))\gamename.csv"
    

    329 个字符长

    vbs 不会对结果进行排序,也不会自动输出到文件。

    以下是运行时测试:

    PS C:\Users\Estranger> measure-command {$s=((gc "C:\Users\Estranger\Downloads\shortcuts.vdf").ToCharArray() | ?{![char]::IsControl("$_")}) -join ""
    >> ($s | sls "(appname)(.*?)(Exe)" -all).matches.value | %{$_.Substring(7,$_.Length-10)} | sort >"$([environment]::getfolderpath('desktop'))\gamename.txt"}
    
    Days              : 0
    Hours             : 0
    Minutes           : 0
    Seconds           : 1
    Milliseconds      : 86
    Ticks             : 10863660
    TotalDays         : 1.25736805555556E-05
    TotalHours        : 0.000301768333333333
    TotalMinutes      : 0.0181061
    TotalSeconds      : 1.086366
    TotalMilliseconds : 1086.366
    
    PS C:\Users\Estranger> measure-command {$s=((gc "C:\Users\Estranger\Downloads\shortcuts.vdf").ToCharArray() | ?{![char]::IsControl("$_")}) -join ""
    >> ($s | sls "(appname)(.*?)(Exe)" -all).matches.value | %{$_.Substring(7,$_.Length-10)} | sort | %{[PSCustomObject]@{GameName=$_}} | epcsv "$([environment]::getfolderpath('desktop'))\gamename.csv"}
    
    Days              : 0
    Hours             : 0
    Minutes           : 0
    Seconds           : 1
    Milliseconds      : 171
    Ticks             : 11716488
    TotalDays         : 1.356075E-05
    TotalHours        : 0.000325458
    TotalMinutes      : 0.01952748
    TotalSeconds      : 1.1716488
    TotalMilliseconds : 1171.6488
    
    PS C:\Users\Estranger> measure-command {cscript steam.vbs}
    
    Days              : 0
    Hours             : 0
    Minutes           : 0
    Seconds           : 1
    Milliseconds      : 338
    Ticks             : 13380483
    TotalDays         : 1.54866701388889E-05
    TotalHours        : 0.000371680083333333
    TotalMinutes      : 0.022300805
    TotalSeconds      : 1.3380483
    TotalMilliseconds : 1338.0483
    

    My first method obviously won, the downvote is unfair, the OP didn't post the critical information, so my code couldn't have solved the OP's problem at first no matter how good I am.


    To whoever downvoted my answer, my answer is now edited and your downvote is no longer locked, please cast votes carefully based on objective facts, and please lift the downvote.

    To the OP, the other answer is, objectively, not as efficient as my answer. You didn't post the right information at first, so I only have incorrect information to work with. No matter how good I am, it is impossible for me to solve your problem because "Garbage In, Garbage Out", the other answerer just got lucky and happened to be online when you posted the right information while I was away, and you see the script is not as good as mine, please consider accept my answer instead.


    Even shorter code:

    Method 1 Golfed

    $s=((gc "C:\Program Files (x86)\Steam\userdata\149576161\config\shortcuts.vdf").ToCharArray() | ?{![char]::IsControl("$_")}) -join ""
    ($s | sls "(?<=appname)(.*?)(?=Exe)" -All).matches.value | sort > "$([environment]::getfolderpath('desktop'))\gamename.txt"
    

    Method 2 Golfed

    $s=((gc "C:\Program Files (x86)\Steam\userdata\149576161\config\shortcuts.vdf").ToCharArray() | ?{![char]::IsControl("$_")}) -join ""
    ($s | sls "(?<=appname)(.*?)(?=Exe)" -All).matches.value | sort | %{[PSCustomObject]@{GameName=$_}} | epcsv "$([environment]::getfolderpath('desktop'))\gamename.csv"
    

    The regex used by these new methods will matches only the game names, but using it increases runtime by 0.3s compared to the first regex.

    This is what I see in console using the second method 1 golfed: 在此处输入图像描述

    I want to answer this question and help the OP simply because I find the question interesting, the thing OP wanted is fun, I am just a beginner in Programming, and I want to improve my skills by answering questions others have posted with programs, that's all...

    P.S. I really want to be a hacker...

    • 0
  3. idbrii
    2021-06-15T13:15:10+08:002021-06-15T13:15:10+08:00

    有一个非官方的vdf python 模块用于解析 Valve 的 vdf 文件。有了它,解析和写出包含所有名称的 csv 非常简单:

    import vdf
    
    def print_names(shortcut_file_path):
        with open(shortcut_file_path, "rb") as f:
            shortcuts = vdf.binary_load(f)
    
        with open('c:/scratch/shortcuts.csv', 'w') as f:
            f.write('Game Name\n')
            for k, v in shortcuts["shortcuts"].items():
                appname = v.get("appname")
                print(appname)
                f.write(appname + '\n')
    
    print_names("C:/Program Files (x86)/Steam/userdata/149576161/config/shortcuts.vdf")
    

    要查看所有可用字段(“appname”除外),请将该print行替换为import pprint; pprint.pprint(v); break

    像其他 python 模块一样,使用pip install vdf.

    • 0

相关问题

  • 如何对整列使用 Excel 的 LENGTH 函数?

  • Excel 数组(2 个变量)

  • 如何从 WSL 打开 office 文件

  • 如果一个字符串出现在正则表达式中的另一个字符串之前,如何停止搜索

  • VBA根据文件名重命名工作表

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    如何减少“vmmem”进程的消耗?

    • 11 个回答
  • Marko Smith

    从 Microsoft Stream 下载视频

    • 4 个回答
  • Marko Smith

    Google Chrome DevTools 无法解析 SourceMap:chrome-extension

    • 6 个回答
  • Marko Smith

    Windows 照片查看器因为内存不足而无法运行?

    • 5 个回答
  • Marko Smith

    支持结束后如何激活 WindowsXP?

    • 6 个回答
  • Marko Smith

    远程桌面间歇性冻结

    • 7 个回答
  • Marko Smith

    子网掩码 /32 是什么意思?

    • 6 个回答
  • Marko Smith

    鼠标指针在 Windows 中按下的箭头键上移动?

    • 1 个回答
  • Marko Smith

    VirtualBox 无法以 VERR_NEM_VM_CREATE_FAILED 启动

    • 8 个回答
  • Marko Smith

    应用程序不会出现在 MacBook 的摄像头和麦克风隐私设置中

    • 5 个回答
  • Martin Hope
    Saaru Lindestøkke 为什么使用 Python 的 tar 库时 tar.xz 文件比 macOS tar 小 15 倍? 2021-03-14 09:37:48 +0800 CST
  • Martin Hope
    CiaranWelsh 如何减少“vmmem”进程的消耗? 2020-06-10 02:06:58 +0800 CST
  • Martin Hope
    Jim Windows 10 搜索未加载,显示空白窗口 2020-02-06 03:28:26 +0800 CST
  • Martin Hope
    v15 为什么通过电缆(同轴电缆)的千兆位/秒 Internet 连接不能像光纤一样提供对称速度? 2020-01-25 08:53:31 +0800 CST
  • Martin Hope
    andre_ss6 远程桌面间歇性冻结 2019-09-11 12:56:40 +0800 CST
  • Martin Hope
    Riley Carney 为什么在 URL 后面加一个点会删除登录信息? 2019-08-06 10:59:24 +0800 CST
  • Martin Hope
    zdimension 鼠标指针在 Windows 中按下的箭头键上移动? 2019-08-04 06:39:57 +0800 CST
  • Martin Hope
    jonsca 我所有的 Firefox 附加组件突然被禁用了,我该如何重新启用它们? 2019-05-04 17:58:52 +0800 CST
  • Martin Hope
    MCK 是否可以使用文本创建二维码? 2019-04-02 06:32:14 +0800 CST
  • Martin Hope
    SoniEx2 更改 git init 默认分支名称 2019-04-01 06:16:56 +0800 CST

热门标签

windows-10 linux windows microsoft-excel networking ubuntu worksheet-function bash command-line hard-drive

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve