如何使用bash脚本选择部分txt文件?

时间:2017-04-04 15:05:22

标签: bash

我有一个logcat.txt文件,我必须从中选择一些字段。我尝试用我的具体案例更好地解释它:

file.txt的

I/Xposed  ( 2559): Droidmon-apimonitor-com.astrolog.great.little.war.game.free:{"timestamp":1463412946569,"result":"","class":"android.os.SystemProperties","method":"get","type":"content","args":["debug.second-display.pkg"]}
I/Xposed  ( 2559): Droidmon-apimonitor-com.astrolog.great.little.war.game.free:{"timestamp":1463412946637,"result":"","class":"android.os.SystemProperties","method":"get","type":"content","args":["gsm.sim.operator.iso-country"]}
I/Xposed  ( 2559): Droidmon-apimonitor-com.astrolog.great.little.war.game.free:{"timestamp":1463412946637,"result":"","class":"android.telephony.TelephonyManager","method":"getSimCountryIso","type":"fingerprint","args":[]}
I/Xposed  ( 2559): Droidmon-apimonitor-com.astrolog.great.little.war.game.free:{"timestamp":1463412949364,"result":"","class":"android.os.SystemProperties","method":"get","type":"content","args":["gsm.sim.operator.iso-country"]}
I/Xposed  ( 2559): Droidmon-apimonitor-com.astrolog.great.little.war.game.free:{"timestamp":1463412949364,"result":"","class":"android.telephony.TelephonyManager","method":"getSimCountryIso","type":"fingerprint","args":[]}
I/Xposed  ( 2559): Droidmon-apimonitor-com.astrolog.great.little.war.game.free:{"timestamp":1463412949365,"class":"android.app.ContextImpl","method":"registerReceiver","type":"binder","args":["horoscope.android.LicenseActivity$3@52828f54",{"mPriority":0,"mActions":["SMS_SENT"],"mHasPartialTypes":false}]}
I/Xposed  ( 2559): Droidmon-apimonitor-com.astrolog.great.little.war.game.free:{"timestamp":1463412949373,"class":"android.app.ContextImpl","method":"registerReceiver","type":"binder","args":["horoscope.android.LicenseActivity$3@52828f54",{"mPriority":0,"mActions":["SMS_SENT"],"mHasPartialTypes":false}]}
I/Xposed  ( 2559): Droidmon-apimonitor-com.astrolog.great.little.war.game.free:{"timestamp":1463412949380,"class":"android.app.ContextImpl","method":"registerReceiver","type":"binder","args":["horoscope.android.LicenseActivity$4@52931658",{"mPriority":0,"mActions":["SMS_DELIVERED"],"mHasPartialTypes":false}]}
I/Xposed  ( 2559): Droidmon-apimonitor-com.astrolog.great.little.war.game.free:{"timestamp":1463412949384,"class":"android.app.ContextImpl","method":"registerReceiver","type":"binder","args":["horoscope.android.LicenseActivity$4@52931658",{"mPriority":0,"mActions":["SMS_DELIVERED"],"mHasPartialTypes":false}]}
I/Xposed  ( 2559): Droidmon-apimonitor-com.astrolog.great.little.war.game.free:{"timestamp":1463412949404,"class":"javax.crypto.spec.SecretKeySpec","method":"javax.crypto.spec.SecretKeySpec","type":"crypto","args":["\n0x00000000 0A F9 E4 5D BB DB CE 8B 57 27 4D 5A 1C 2A 37 7D ...]....W'MZ.*7}","AES"]}
I/Xposed  ( 2559): Droidmon-apimonitor-com.astrolog.great.little.war.game.free:{"timestamp":1463412949404,"class":"javax.crypto.spec.SecretKeySpec","method":"javax.crypto.spec.SecretKeySpec","type":"crypto","args":["\n0x00000000 0A F9 E4 5D BB DB CE 8B 57 27 4D 5A 1C 2A 37 7D ...]....W'MZ.*7}","AES"]}

所以从这个文件我必须为每一行选择" class":" "," method":&#34 ; &#34 ;.结果必须是这样的:

{"class":"android.os.SystemProperties","method":"get"}
{"class":"android.os.SystemProperties","method":"get"} {"class":"android.telephony.TelephonyManager","method":"getSimCountryIso"} {"class":"android.os.SystemProperties","method":"get"} {"class":"android.telephony.TelephonyManager","method":"getSimCountryIso"} {"class":"javax.crypto.spec.SecretKeySpec","method":"javax.crypto.spec.SecretKeySpec"} {"class":"javax.crypto.spec.SecretKeySpec","method":"javax.crypto.spec.SecretKeySpec"}

我尝试使用sed命令执行此操作,但我无法做到。

4 个答案:

答案 0 :(得分:0)

您可以尝试使用sed:

sed 's/^.*"class":"([^"]*)".*"method":"([^"]*)".*$/{"class":"\1","method":"\2"}/gp' file.txt -nr

答案 1 :(得分:0)

这个怎么样:

sed 's/.*\("class":"[a-zA-Z\.]*","method":"[a-zA-Z\.]*"\).*/\{\1\}/' logcat.txt

这基本上是基于一个大捕获组的匹配。我假设类字段和方法字段只包含字母字符和'。'。你可能需要调整。

答案 2 :(得分:0)

直接在bash中解析JSON会很困难,使用sed可能很难维护(如果要扩展结果集,或者JSON键排序是动态的)。

但是,如果您不反对使用内联python,可以在一行中完成:

cut -d: -f3- file.txt | while read line; do \
    echo $line |\
    python -c "import sys, json; obj = json.load(sys.stdin); trimmed = {'class': obj['class'], 'method': obj['method']}; print(json.dumps(trimmed));"; \
done

它也不是最友好的解决方案,但它将采用file.txt的仅JSON部分,将其逐行传递给将仅选择和输出的python代码您感兴趣的部分。

要扩展输出,您只需要在python脚本内部添加更多内容。

答案 3 :(得分:0)

在bash中解析json时,我总是会使用jq之类的东西。试试这个

grep -oE '\{.*\}' file.txt | jq -r '{"class":.class,"method":.method}'

-o标记仅选择匹配的内容,因此grep括号内的所有内容(除了在json中之外没有括号)并将其发送到jq

如果您知道模式great.little.war.game.free将始终存在,您还可以使用正则表达式断言和后观:

grep -oP '(?<=great.little.war.game.free:).*' file.txt | jq -r '{"class":.class,"method":.method}'

来自here