在 AWK 中打印带有变量的字符串
Print string with variables in AWK
我正在尝试从 phone 解析 android 包列表。
示例数据如下所示。
Package [com.google.android.as] (9faf0bc):
userId=10320
pkg=Package{299f845 com.google.android.as}
codePath=/system/priv-app/DevicePersonalizationServices
resourcePath=/system/priv-app/DevicePersonalizationServices
legacyNativeLibraryDir=/system/priv-app/DevicePersonalizationServices/lib
primaryCpuAbi=arm64-v8a
secondaryCpuAbi=null
versionCode=4371429 minSdk=30 targetSdk=30
versionName=R.3.sysimg.oem.325908743
splits=[base]
apkSigningVersion=0
applicationInfo=ApplicationInfo{299f845 com.google.android.as}
flags=[ SYSTEM HAS_CODE ALLOW_CLEAR_USER_DATA ALLOW_BACKUP ]
privateFlags=[ PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION ALLOW_AUDIO_PLAYBACK_CAPTURE PRIVILEGED PRIVATE_FLAG_ALLOW_NATIVE_HEAP_POINTER_TAGGING ]
forceQueryable=false
queriesPackages=[]
dataDir=/data/user/0/com.google.android.as
supportsScreens=[small, medium, large, xlarge, resizeable, anyDensity]
timeStamp=2008-12-31 20:30:00
firstInstallTime=2008-12-31 20:30:00
lastUpdateTime=2008-12-31 20:30:00
signatures=PackageSignatures{f91eb9a version:0, signatures:[], past signatures:[]}
installPermissionsFixed=false
pkgFlags=[ SYSTEM HAS_CODE ALLOW_CLEAR_USER_DATA ALLOW_BACKUP ]
install permissions:
android.permission.MODIFY_AUDIO_ROUTING: granted=true
android.permission.SYSTEM_ALERT_WINDOW: granted=true
<< multiple lines >>
android.permission.READ_DEVICE_CONFIG: granted=true
android.permission.READ_OEM_UNLOCK_STATE: granted=true
User 0: ceDataInode=0 installed=true hidden=false suspended=false distractionFlags=0 stopped=false notLaunched=false enabled=0 instant=false virtual=false
gids=[3002, 3003, 3001]
User 150: ceDataInode=0 installed=true hidden=false suspended=false distractionFlags=0 stopped=false notLaunched=false enabled=0 instant=false virtual=false
gids=[3002, 3003, 3001]
Package [com.google.android.gm] (a066ccb):
userId=10230
pkg=Package{9e45ca8 com.google.android.gm}
codePath=/system/app/Gmail2
resourcePath=/system/app/Gmail2
legacyNativeLibraryDir=/system/app/Gmail2/lib
primaryCpuAbi=null
secondaryCpuAbi=null
versionCode=62209002 minSdk=21 targetSdk=29
versionName=2020.05.31.316831277.release
splits=[base]
apkSigningVersion=0
applicationInfo=ApplicationInfo{9e45ca8 com.google.android.gm}
flags=[ SYSTEM HAS_CODE ALLOW_CLEAR_USER_DATA ALLOW_BACKUP KILL_AFTER_RESTORE RESTORE_ANY_VERSION ]
privateFlags=[ PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE ALLOW_AUDIO_PLAYBACK_CAPTURE PRIVATE_FLAG_REQUEST_LEGACY_EXTERNAL_STORAGE HAS_DOMAIN_URLS PRIVATE_FLAG_ALLOW_NATIVE_HEAP_POINTER_TAGGING ]
forceQueryable=false
queriesIntents=[Intent { act=android.support.customtabs.action.CustomTabsService }, Intent { act=android.intent.action.VIEW cat=[android.intent.category.BROWSABLE] dat=http://www.example.com/... }, Intent { act=android.intent.action.VIEW cat=[android.intent.category.BROWSABLE] dat=http://www.example.com/... }, Intent { act=android.support.customtabs.action.CustomTabsService }]
dataDir=/data/user/0/com.google.android.gm
supportsScreens=[small, medium, large, xlarge, resizeable, anyDensity]
usesLibraries:
android.test.base
usesOptionalLibraries:
org.apache.http.legacy
timeStamp=2008-12-31 20:30:00
firstInstallTime=2008-12-31 20:30:00
lastUpdateTime=2008-12-31 20:30:00
signatures=PackageSignatures{c66d3c1 version:0, signatures:[], past signatures:[]}
installPermissionsFixed=false
pkgFlags=[ SYSTEM HAS_CODE ALLOW_CLEAR_USER_DATA ALLOW_BACKUP KILL_AFTER_RESTORE RESTORE_ANY_VERSION ]
declared permissions:
com.google.android.gm.email.permission.READ_ATTACHMENT: prot=signature
com.google.android.gm.email.permission.ACCESS_PROVIDER: prot=signature
<< multiple lines >>
com.android.launcher.permission.INSTALL_SHORTCUT: granted=true
com.google.android.gms.permission.REQUEST_SCREEN_LOCK_COMPLEXITY: granted=true
android.permission.WAKE_LOCK: granted=true
User 0: ceDataInode=0 installed=true hidden=false suspended=false distractionFlags=0 stopped=false notLaunched=false enabled=0 instant=false virtual=false
gids=[3003]
User 150: ceDataInode=0 installed=true hidden=false suspended=false distractionFlags=0 stopped=false notLaunched=false enabled=0 instant=false virtual=false
gids=[3003]
为了在 AWK 中解析数据,我使用下面的命令
dumpsys package | awk '/^[ ]*Package \[.*\] (.*)/ { i = index([=11=], "[") + 1; pkg = substr([=11=], i, index([=11=], "]") - i); } /[ ]*versionCode=/ /[ ]*versionName=/ /[ ]*firstInstallTime=/ /[ ]*lastUpdateTime=/ { { print "START PackageName=" pkg [=11=] " END"; pkg = ""; } }'
以上命令的输出如下
versionCode=4371429 minSdk=30 targetSdk=30 versionName=R.3.sysimg.oem.325908743 firstInstallTime=2008-12-31 20:30:00START PackageName=com.google.android.as lastUpdateTime=2008-12-31 20:30:00 END versionCode=62209002 minSdk=21 targetSdk=29 versionName=2020.05.31.316831277.release firstInstallTime=2008-12-31 20:30:00START PackageName=com.google.android.gm lastUpdateTime=2008-12-31 20:30:00 END
问题是数据输出的顺序。预期的输出应按打印顺序在 START 和 END 之间。我无法获得所需的结构化数据。
请指教
EDIT2
一行输出一个包的数据,以制表符分隔,
将 | paste - - - -
附加到 awk
命令,即每个破折号
选择的 4 个属性。
paste
有一个 -d
选项来指定分隔符。
或者你可以使用我原来的答案,它是这样做的 - 具有指定顺序的属性 - 如果你将 -v isheader=""
传递给 awk
。
编辑
第二次尝试,可能是我看错了:
dumpsys package | awk '
/^[ ]*Package \[/ {
pkg = substr(,2,length()-2)
}
/^[ ]*(versionCode|versionName|firstInstallTime|lastUpdateTime)=/ {
print "START PackageName=" pkg [=10=] " END"
}
'
或者,作为单行:
dumpsys package | awk '/^[ ]*Package \[/ { pkg = substr(,2,length()-2); } /^[ ]*(versionCode|versionName|firstInstallTime|lastUpdateTime)=/ { print "START PackageName=" pkg [=11=] " END"; }'
输出:
START PackageName=com.google.android.as versionCode=4371429 minSdk=30 targetSdk=30 END
START PackageName=com.google.android.as versionName=R.3.sysimg.oem.325908743 END
START PackageName=com.google.android.as firstInstallTime=2008-12-31 20:30:00 END
START PackageName=com.google.android.as lastUpdateTime=2008-12-31 20:30:00 END
START PackageName=com.google.android.gm versionCode=62209002 minSdk=21 targetSdk=29 END
START PackageName=com.google.android.gm versionName=2020.05.31.316831277.release END
START PackageName=com.google.android.gm firstInstallTime=2008-12-31 20:30:00 END
START PackageName=com.google.android.gm lastUpdateTime=2008-12-31 20:30:00 END
你非常接近,但是正则表达式之间缺少 ||
个运算符,并且 pkg
在第二个 awk 模式中被重置为空字符串。
(原回答如下)
您发布的输出基本上是一个带有键值对的 conf 文件
对,但每个 'Package' 部分重复。
以下 awk
脚本收集给定属性的值
在关联数组 (Val
) 的 att
变量中并打印
数组作为制表符分隔值 (TSV),每节一行,在
指定顺序。
OFS
是 awk
的输出字段分隔符。喜欢 att
和 isheader
可以在 awk
命令行上指定变量 OFS
。
它默认在此处使用制表符,但可以使用 ofs="\n"
或
ofs="|"
例如。
与mawk
或gawk
一起使用:
: ${ofs=$(printf '\t')}
dumpsys-command |
awk -v OFS="${ofs}" -v isheader="" -f '/path/to/script' |
while IFS="${ofs}" read -r pkg vcode vname dt1st dtupd
do printf '%s\n' '# -----' \
"Package: ${pkg}" \
"Version code: ${vcode}" \
"Last update: ${dtupd}"
done
BEGIN {
regexSectionStart = "^ *Package "
keyvalsep = "="
if ( !att )
att="pkg versionCode versionName firstInstallTime lastUpdateTime"
split(att, Att, " ")
for ( i in Att )
Idx[Att[i]] = i
if ( isheader )
emitArr(Att)
}
[=14=] ~ regexSectionStart {
emitArr(Val)
for ( i in Val )
delete Val[i]
next
}
{
key = substr(, 1, -1+index(,keyvalsep))
if ( key in Idx )
Val[Idx[key]] = substr([=14=], 1+index([=14=],keyvalsep))
}
## Print array in index order, skip if empty
function emitArr(V, i,s) {
for ( i in V ) {
for ( i=1; i<=length(V); i++ )
s = s (i==1 ? "" : OFS) V[i]
print s
return
}
}
END{ emitArr(Val); }
awk
脚本 (isheader="x"
) 的输出:
pkg versionCode versionName firstInstallTime lastUpdateTime
Package{299f845 com.google.android.as} 4371429 minSdk=30 targetSdk=30 R.3.sysimg.oem.325908743 2008-12-31 20:30:00 2008-12-31 20:30:00
Package{9e45ca8 com.google.android.gm} 62209002 minSdk=21 targetSdk=29 2020.05.31.316831277.release 2008-12-31 20:30:00 2008-12-31 20:30:00
shell 脚本的输出:
# -----
Package: Package{299f845 com.google.android.as}
Version code: 4371429 minSdk=30 targetSdk=30
Last update: 2008-12-31 20:30:00
# -----
Package: Package{9e45ca8 com.google.android.gm}
Version code: 62209002 minSdk=21 targetSdk=29
Last update: 2008-12-31 20:30:00
我正在尝试从 phone 解析 android 包列表。 示例数据如下所示。
Package [com.google.android.as] (9faf0bc):
userId=10320
pkg=Package{299f845 com.google.android.as}
codePath=/system/priv-app/DevicePersonalizationServices
resourcePath=/system/priv-app/DevicePersonalizationServices
legacyNativeLibraryDir=/system/priv-app/DevicePersonalizationServices/lib
primaryCpuAbi=arm64-v8a
secondaryCpuAbi=null
versionCode=4371429 minSdk=30 targetSdk=30
versionName=R.3.sysimg.oem.325908743
splits=[base]
apkSigningVersion=0
applicationInfo=ApplicationInfo{299f845 com.google.android.as}
flags=[ SYSTEM HAS_CODE ALLOW_CLEAR_USER_DATA ALLOW_BACKUP ]
privateFlags=[ PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION ALLOW_AUDIO_PLAYBACK_CAPTURE PRIVILEGED PRIVATE_FLAG_ALLOW_NATIVE_HEAP_POINTER_TAGGING ]
forceQueryable=false
queriesPackages=[]
dataDir=/data/user/0/com.google.android.as
supportsScreens=[small, medium, large, xlarge, resizeable, anyDensity]
timeStamp=2008-12-31 20:30:00
firstInstallTime=2008-12-31 20:30:00
lastUpdateTime=2008-12-31 20:30:00
signatures=PackageSignatures{f91eb9a version:0, signatures:[], past signatures:[]}
installPermissionsFixed=false
pkgFlags=[ SYSTEM HAS_CODE ALLOW_CLEAR_USER_DATA ALLOW_BACKUP ]
install permissions:
android.permission.MODIFY_AUDIO_ROUTING: granted=true
android.permission.SYSTEM_ALERT_WINDOW: granted=true
<< multiple lines >>
android.permission.READ_DEVICE_CONFIG: granted=true
android.permission.READ_OEM_UNLOCK_STATE: granted=true
User 0: ceDataInode=0 installed=true hidden=false suspended=false distractionFlags=0 stopped=false notLaunched=false enabled=0 instant=false virtual=false
gids=[3002, 3003, 3001]
User 150: ceDataInode=0 installed=true hidden=false suspended=false distractionFlags=0 stopped=false notLaunched=false enabled=0 instant=false virtual=false
gids=[3002, 3003, 3001]
Package [com.google.android.gm] (a066ccb):
userId=10230
pkg=Package{9e45ca8 com.google.android.gm}
codePath=/system/app/Gmail2
resourcePath=/system/app/Gmail2
legacyNativeLibraryDir=/system/app/Gmail2/lib
primaryCpuAbi=null
secondaryCpuAbi=null
versionCode=62209002 minSdk=21 targetSdk=29
versionName=2020.05.31.316831277.release
splits=[base]
apkSigningVersion=0
applicationInfo=ApplicationInfo{9e45ca8 com.google.android.gm}
flags=[ SYSTEM HAS_CODE ALLOW_CLEAR_USER_DATA ALLOW_BACKUP KILL_AFTER_RESTORE RESTORE_ANY_VERSION ]
privateFlags=[ PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE ALLOW_AUDIO_PLAYBACK_CAPTURE PRIVATE_FLAG_REQUEST_LEGACY_EXTERNAL_STORAGE HAS_DOMAIN_URLS PRIVATE_FLAG_ALLOW_NATIVE_HEAP_POINTER_TAGGING ]
forceQueryable=false
queriesIntents=[Intent { act=android.support.customtabs.action.CustomTabsService }, Intent { act=android.intent.action.VIEW cat=[android.intent.category.BROWSABLE] dat=http://www.example.com/... }, Intent { act=android.intent.action.VIEW cat=[android.intent.category.BROWSABLE] dat=http://www.example.com/... }, Intent { act=android.support.customtabs.action.CustomTabsService }]
dataDir=/data/user/0/com.google.android.gm
supportsScreens=[small, medium, large, xlarge, resizeable, anyDensity]
usesLibraries:
android.test.base
usesOptionalLibraries:
org.apache.http.legacy
timeStamp=2008-12-31 20:30:00
firstInstallTime=2008-12-31 20:30:00
lastUpdateTime=2008-12-31 20:30:00
signatures=PackageSignatures{c66d3c1 version:0, signatures:[], past signatures:[]}
installPermissionsFixed=false
pkgFlags=[ SYSTEM HAS_CODE ALLOW_CLEAR_USER_DATA ALLOW_BACKUP KILL_AFTER_RESTORE RESTORE_ANY_VERSION ]
declared permissions:
com.google.android.gm.email.permission.READ_ATTACHMENT: prot=signature
com.google.android.gm.email.permission.ACCESS_PROVIDER: prot=signature
<< multiple lines >>
com.android.launcher.permission.INSTALL_SHORTCUT: granted=true
com.google.android.gms.permission.REQUEST_SCREEN_LOCK_COMPLEXITY: granted=true
android.permission.WAKE_LOCK: granted=true
User 0: ceDataInode=0 installed=true hidden=false suspended=false distractionFlags=0 stopped=false notLaunched=false enabled=0 instant=false virtual=false
gids=[3003]
User 150: ceDataInode=0 installed=true hidden=false suspended=false distractionFlags=0 stopped=false notLaunched=false enabled=0 instant=false virtual=false
gids=[3003]
为了在 AWK 中解析数据,我使用下面的命令
dumpsys package | awk '/^[ ]*Package \[.*\] (.*)/ { i = index([=11=], "[") + 1; pkg = substr([=11=], i, index([=11=], "]") - i); } /[ ]*versionCode=/ /[ ]*versionName=/ /[ ]*firstInstallTime=/ /[ ]*lastUpdateTime=/ { { print "START PackageName=" pkg [=11=] " END"; pkg = ""; } }'
以上命令的输出如下
versionCode=4371429 minSdk=30 targetSdk=30 versionName=R.3.sysimg.oem.325908743 firstInstallTime=2008-12-31 20:30:00START PackageName=com.google.android.as lastUpdateTime=2008-12-31 20:30:00 END versionCode=62209002 minSdk=21 targetSdk=29 versionName=2020.05.31.316831277.release firstInstallTime=2008-12-31 20:30:00START PackageName=com.google.android.gm lastUpdateTime=2008-12-31 20:30:00 END
问题是数据输出的顺序。预期的输出应按打印顺序在 START 和 END 之间。我无法获得所需的结构化数据。 请指教
EDIT2
一行输出一个包的数据,以制表符分隔,
将 | paste - - - -
附加到 awk
命令,即每个破折号
选择的 4 个属性。
paste
有一个 -d
选项来指定分隔符。
或者你可以使用我原来的答案,它是这样做的 - 具有指定顺序的属性 - 如果你将 -v isheader=""
传递给 awk
。
编辑
第二次尝试,可能是我看错了:
dumpsys package | awk '
/^[ ]*Package \[/ {
pkg = substr(,2,length()-2)
}
/^[ ]*(versionCode|versionName|firstInstallTime|lastUpdateTime)=/ {
print "START PackageName=" pkg [=10=] " END"
}
'
或者,作为单行:
dumpsys package | awk '/^[ ]*Package \[/ { pkg = substr(,2,length()-2); } /^[ ]*(versionCode|versionName|firstInstallTime|lastUpdateTime)=/ { print "START PackageName=" pkg [=11=] " END"; }'
输出:
START PackageName=com.google.android.as versionCode=4371429 minSdk=30 targetSdk=30 END
START PackageName=com.google.android.as versionName=R.3.sysimg.oem.325908743 END
START PackageName=com.google.android.as firstInstallTime=2008-12-31 20:30:00 END
START PackageName=com.google.android.as lastUpdateTime=2008-12-31 20:30:00 END
START PackageName=com.google.android.gm versionCode=62209002 minSdk=21 targetSdk=29 END
START PackageName=com.google.android.gm versionName=2020.05.31.316831277.release END
START PackageName=com.google.android.gm firstInstallTime=2008-12-31 20:30:00 END
START PackageName=com.google.android.gm lastUpdateTime=2008-12-31 20:30:00 END
你非常接近,但是正则表达式之间缺少 ||
个运算符,并且 pkg
在第二个 awk 模式中被重置为空字符串。
(原回答如下)
您发布的输出基本上是一个带有键值对的 conf 文件 对,但每个 'Package' 部分重复。
以下 awk
脚本收集给定属性的值
在关联数组 (Val
) 的 att
变量中并打印
数组作为制表符分隔值 (TSV),每节一行,在
指定顺序。
OFS
是 awk
的输出字段分隔符。喜欢 att
和 isheader
可以在 awk
命令行上指定变量 OFS
。
它默认在此处使用制表符,但可以使用 ofs="\n"
或
ofs="|"
例如。
与mawk
或gawk
一起使用:
: ${ofs=$(printf '\t')}
dumpsys-command |
awk -v OFS="${ofs}" -v isheader="" -f '/path/to/script' |
while IFS="${ofs}" read -r pkg vcode vname dt1st dtupd
do printf '%s\n' '# -----' \
"Package: ${pkg}" \
"Version code: ${vcode}" \
"Last update: ${dtupd}"
done
BEGIN {
regexSectionStart = "^ *Package "
keyvalsep = "="
if ( !att )
att="pkg versionCode versionName firstInstallTime lastUpdateTime"
split(att, Att, " ")
for ( i in Att )
Idx[Att[i]] = i
if ( isheader )
emitArr(Att)
}
[=14=] ~ regexSectionStart {
emitArr(Val)
for ( i in Val )
delete Val[i]
next
}
{
key = substr(, 1, -1+index(,keyvalsep))
if ( key in Idx )
Val[Idx[key]] = substr([=14=], 1+index([=14=],keyvalsep))
}
## Print array in index order, skip if empty
function emitArr(V, i,s) {
for ( i in V ) {
for ( i=1; i<=length(V); i++ )
s = s (i==1 ? "" : OFS) V[i]
print s
return
}
}
END{ emitArr(Val); }
awk
脚本 (isheader="x"
) 的输出:
pkg versionCode versionName firstInstallTime lastUpdateTime
Package{299f845 com.google.android.as} 4371429 minSdk=30 targetSdk=30 R.3.sysimg.oem.325908743 2008-12-31 20:30:00 2008-12-31 20:30:00
Package{9e45ca8 com.google.android.gm} 62209002 minSdk=21 targetSdk=29 2020.05.31.316831277.release 2008-12-31 20:30:00 2008-12-31 20:30:00
shell 脚本的输出:
# -----
Package: Package{299f845 com.google.android.as}
Version code: 4371429 minSdk=30 targetSdk=30
Last update: 2008-12-31 20:30:00
# -----
Package: Package{9e45ca8 com.google.android.gm}
Version code: 62209002 minSdk=21 targetSdk=29
Last update: 2008-12-31 20:30:00