Print string with variables in AWK

271 views Asked by At

I am trying to parse android package list from phone. Sample data is as shown below.

  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]

To parse data in AWK, I am using the command as under

dumpsys package | awk '/^[ ]*Package \[.*\] (.*)/ { i = index($0, "[") + 1; pkg = substr($0, i, index($0, "]") - i); } /[ ]*versionCode=/ /[ ]*versionName=/  /[ ]*firstInstallTime=/ /[ ]*lastUpdateTime=/ { { print "START PackageName=" pkg $0 " END"; pkg = ""; } }'

Output of the above command is as under

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

The problem is the order of data output. The expected output should be in order between START and END as being printed. I am not able to get the structured data as desired. Please advise.

1

There are 1 answers

6
urznow On BEST ANSWER

EDIT2

To output data for one package on one line, delimited by tabs, append | paste - - - - to the awk command, i.e. one dash for each of the 4 attributes selected. paste has a -d option to specify a delimiter.

Or you could use my original answer which did that - with attributes in specified order - if you passed -v isheader="" to awk.

EDIT

Second attempt, perhaps I misread:

dumpsys package | awk '
/^[ ]*Package \[/ { 
    pkg = substr($2,2,length($2)-2)
}
/^[ ]*(versionCode|versionName|firstInstallTime|lastUpdateTime)=/ { 
    print "START PackageName=" pkg $0 " END"
}
'

or, as a one-liner:

dumpsys package | awk '/^[ ]*Package \[/ { pkg = substr($2,2,length($2)-2); } /^[ ]*(versionCode|versionName|firstInstallTime|lastUpdateTime)=/ { print "START PackageName=" pkg $0 " END"; }'

Output:

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

You were very close but || operators were missing between regexes, and pkg was reset to an empty string in the second awk pattern.


(Original answer follows)

The output you posted is basically a conf file with key-value pairs but repeated for each 'Package' section.

The following awk script collects the values for attributes given in the att variable in an associative array (Val) and prints the array as tab-separated values (TSV) in one line per section, in the specified order.

OFS is awk's output field separator. Like the att and isheader variables OFS can be specified on the awk command line. It defaults to tab here but can be overridden with ofs="\\n" or ofs="|" for example.

Use with mawk or gawk as:

: ${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)
}
$0 ~ regexSectionStart {
    emitArr(Val)
    for ( i in Val )
        delete Val[i]
    next
}
{
    key = substr($1, 1, -1+index($1,keyvalsep))
    if ( key in Idx )
        Val[Idx[key]] = substr($0, 1+index($0,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); }

Output from awk script (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

Output from shell script:

# -----
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