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

如何使用bash脚本选择txt文件的一部分?,bash,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"

我有一个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"]}
因此,从这个文件中,我必须为每一行选择“类”:“方法”:”。结果必须是这样的:

{“类”:“android.os.SystemProperties”,“方法”:“get”}

{“类”:“android.os.SystemProperties”,“方法”:“get”}
{“类”:“android.telephony.TelephonyManager”,“方法”:“getSimCountryIso”}
{“类”:“android.os.SystemProperties”,“方法”:“get”}
{“类”:“android.telephony.TelephonyManager”,“方法”:“getSimCountryIso”}
{“类”:“javax.crypto.spec.SecretKeySpec”,“方法”:“javax.crypto.spec.SecretKeySpec”}
{“类”:“javax.crypto.spec.SecretKeySpec”,“方法”:“javax.crypto.spec.SecretKeySpec”}

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

您可以尝试使用sed:

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

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

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

在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代码将只选择并输出您感兴趣的部分


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

在bash中解析json时,我总是使用类似的方法。试试这个

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}'

grep-oP'(?请发布您尝试过的sed命令和您获得的输出,我认为它没有用。它很有用,因为a)它显示您尝试解决问题,b)允许某人解决问题,并显示您做错了什么。如何删除大括号{}之前的所有文本,在本例中为I/Xposed(2559):Droidmon-apimonitor-com.astrolog.great.little.war.game.free:?通过这种方式,我可以使用jq来提取通缉字段。我假设始终会有一行“great.little.war.game.free”,然后grep命令会删除括号之前的所有内容。如果情况并非如此,则需要采取其他措施对其进行过滤out@danieledaquale我已经更新了我的答案(我想)来解决您的问题您的假设是正确的,但是这个命令返回一个无效的输出。只要您在输入文件中使用sed,这个正则表达式就可以工作。最新答案