Apple stores Address Book Data in a local sqlite3
databse. I want to export the name and number in a clean and consistent format for all contacts
The database is located in: /Users/kellygold/Library/Application\ Support/AddressBook/Sources/<RANDOMSTRING>/AddressBook-v22.abcddb
where RANDOMSTRING is a generated file name
Inside the DB there is a table ZABCDPHONENUMBER
with field ZFULLNUMBER
but the values are not stored consistently
NOTE the different formats: (111) 222-3333, +12223334444, 1112223333, +1 (222) 333-4444
. Some numbers appear in only one format, some numbers have multiple rows with multiple formats for same contact
Query to produce this:
SELECT DISTINCT
ZABCDRECORD.ZFIRSTNAME [FIRST NAME],
ZABCDRECORD.ZLASTNAME [LAST NAME],
ZABCDPHONENUMBER.ZFULLNUMBER [FULL NUMBER]
FROM
ZABCDRECORD
LEFT JOIN ZABCDPHONENUMBER ON ZABCDRECORD.Z_PK = ZABCDPHONENUMBER.ZOWNER
ORDER BY
ZABCDRECORD.ZLASTNAME,
ZABCDRECORD.ZFIRSTNAME,
ZABCDPHONENUMBER.ZORDERINGINDEX ASC
Desired output flat with preceeding country code optional:
FIRST NAME, LAST NAME, FULL NUMBER
asdf, fghj, 2223334444
bbbb, cccc, 12223334444
Currently I process the data by exporting the SQLITE query as JSON and running this very hacky solution
cat adbExport.json| jq '.[] | select(.["FULL NUMBER"] != null)' | sed 's/+//g'\ | sed 's/ //g' | sed 's/-//g' | sed 's/(//g'| sed 's/)//g' | jq '{FIRSTNAME: .FIRSTNAME, LASTNAME: .LASTNAME, FULLNUMBER: ("+1"+ .FULLNUMBER)}' | sed 's/+11/+1/g' > cleanContacts.json
This produces valid JSON which I can use. (data obfuscated for security)
...
{
"FIRSTNAME": "AnXXX",
"LASTNAME": "ZuckXXX",
"FULLNUMBER": "2068901111"
}
{
"FIRSTNAME": "Nick",
"LASTNAME": "fromHay",
"FULLNUMBER": "262443XXXX"
}
...
How can I do this directly from the Database query?
Try this :
#!/usr/bin/env bash
sqlite3 ~/Library/"Application Support"/AddressBook/Sources/*/AddressBook-v22.abcddb<<EOF
.mode json
SELECT DISTINCT
ZABCDRECORD.ZFIRSTNAME [FIRST NAME],
ZABCDRECORD.ZLASTNAME [LAST NAME],
ZABCDPHONENUMBER.ZFULLNUMBER [FULL NUMBER]
FROM
ZABCDRECORD
LEFT JOIN ZABCDPHONENUMBER ON ZABCDRECORD.Z_PK = ZABCDPHONENUMBER.ZOWNER
ORDER BY
ZABCDRECORD.ZLASTNAME,
ZABCDRECORD.ZFIRSTNAME,
ZABCDPHONENUMBER.ZORDERINGINDEX ASC;
EOF
The result I get is :
[{"FIRST NAME":null,"LAST NAME":null,"FULL NUMBER":null},
{"FIRST NAME":"Philippe","LAST NAME":"surname","FULL NUMBER":"+188888888"}]
Update
You list of commands can be done with a single call of jq :
jq '.[]["FULL NUMBER"] |= gsub("[ ()+]";"")' adbExport.json
You can also do it in SQL with an extension : replace a part of a string with REGEXP in sqlite3