Reshaping json / reparing json inside shell script (remove trailing comma)find statement inside backticks not recognised inside shell scriptRemove lines in a shell scriptWrite permissions inside shell scriptShell script taking me inside the serversource inside a shell scriptReplace the comma with vertical bar |, except when inside double quotes, and remove double quotesRemoval of double quotes and substitution of comma inside itlooping through JSON array in shell scriptshell script inside dockerUse line break in JSON inside a shell script
Processor speed limited at 0.4 Ghz
Bullying boss launched a smear campaign and made me unemployable
How dangerous is XSS
Is it a bad idea to plug the other end of ESD strap to wall ground?
How to compactly explain secondary and tertiary characters without resorting to stereotypes?
Why are UK visa biometrics appointments suspended at USCIS Application Support Centers?
Rotate ASCII Art by 45 Degrees
Finitely generated matrix groups whose eigenvalues are all algebraic
How to prevent "they're falling in love" trope
Calculate the Mean mean of two numbers
Do Iron Man suits sport waste management systems?
How can I deal with my CEO asking me to hire someone with a higher salary than me, a co-founder?
Why is the sentence "Das ist eine Nase" correct?
What is required to make GPS signals available indoors?
Was the Stack Exchange "Happy April Fools" page fitting with the '90's code?
Mathematica command that allows it to read my intentions
Knowledge-based authentication using Domain-driven Design in C#
Ambiguity in the definition of entropy
What exactly is ineptocracy?
How exploitable/balanced is this homebrew spell: Spell Permanency?
Why was Sir Cadogan fired?
Do creatures with a listed speed of "0 ft., fly 30 ft. (hover)" ever touch the ground?
What is the fastest integer factorization to break RSA?
GFCI outlets - can they be repaired? Are they really needed at the end of a circuit?
Reshaping json / reparing json inside shell script (remove trailing comma)
find statement inside backticks not recognised inside shell scriptRemove lines in a shell scriptWrite permissions inside shell scriptShell script taking me inside the serversource inside a shell scriptReplace the comma with vertical bar |, except when inside double quotes, and remove double quotesRemoval of double quotes and substitution of comma inside itlooping through JSON array in shell scriptshell script inside dockerUse line break in JSON inside a shell script
I've googled around a lot for this and it seems there is no precursor to this need.
I need to edit an applications preference file programatically : as part of a shell script.
and the prefs are stored in strict json format : this means the app loading that preference file will crash at startup if there is a comma ,
before a closing curly brace }
.
normally this wouldn't be an issue.
I'd just use my sed
s accordingly : if the line containing my faulty text lines up at the end of a section in my example file, then when replacing this text I will always put it without a comma.
If another line containing another faulty bit I want to replace is not at the end, I always replace it including a comma.
Example :
(I use underscore _
as my sed's delimiter because the stings to replace are full of backslashes sometimes)
sed -i 's_"executableDecorator".*_"executableDecorator": "'$user_path'/faf/run \"%s\"",_' $user_path/.faforever/client.prefs
if that line was at the end :
sed -i 's_"executableDecorator".*_"executableDecorator": "'$user_path'/faf/run \"%s\""_' $user_path/.faforever/client.prefs
this would work, But!...
I have the app end before I run my script so that both aren't editing the preferences at the same time, but even still, because of this app's asynchronous execution the preferences my script will be receiving will differ every time.
it's completely random.
sometimes a line could be in the middle sometimes at the end. The app itself (Java & some json java lib) knows how to append comma or not depending on the context but as part of my shell script... I feel things are going to get bloated.
(If not and there's a shorthand to ensure I have comma or not depending on if next line is }
, then that is a better simpler solution that I would be more interested in)
But as it stands I'm looking for a POSIX utility that fixes json so that I can "sanitize" my json prefs file as soon as I'm done butchering it all within my shell script ...does such a thing exist?
EDIT :
here's the base file (whole file, ) :
"mainWindow":
"width": 800,
"height": 600,
"maximized": false,
"lastView": "NEWS",
"lastChildViews": ,
"x": 67.0,
"y": 27.0
,
"forgedAlliance":
"customMapsDirectory": "/home/t/My Games/Gas Powered Games/Supreme Commander Forged Alliance/Maps",
"preferencesFile": "/home/t/.wine/drive_c/users/t/Application Data/Gas Powered Games/Supreme Commander Forged Alliance/Game.prefs",
"officialMapsDirectory": "/home/t/faf/./Maps",
"modsDirectory": "/home/t/My Games/Gas Powered Games/Supreme Commander Forged Alliance/Mods",
"port": 6112,
"autoDownloadMaps": true,
"executableDecorator": ""%s""
,
"login":
"username": "tatsu",
"password": "*******",
"autoLogin": true
,
"chat":
"zoom": 1.0,
"learnedAutoComplete": false,
"previewImageUrls": true,
"maxMessages": 500,
"chatColorMode": "CUSTOM",
"channelTabScrollPaneWidth": 250,
"userToColor": ,
"hideFoeMessages": true,
"timeFormat": "AUTO",
"chatFormat": "COMPACT",
"idleThreshold": 10
,
"notification":
"soundsEnabled": true,
"transientNotificationsEnabled": true,
"mentionSoundEnabled": true,
"infoSoundEnabled": true,
"warnSoundEnabled": true,
"errorSoundEnabled": true,
"friendOnlineToastEnabled": true,
"friendOfflineToastEnabled": true,
"ladder1v1ToastEnabled": true,
"friendOnlineSoundEnabled": true,
"friendOfflineSoundEnabled": true,
"friendJoinsGameSoundEnabled": true,
"friendPlaysGameSoundEnabled": true,
"friendPlaysGameToastEnabled": true,
"privateMessageSoundEnabled": true,
"privateMessageToastEnabled": true,
"friendJoinsGameToastEnabled": true,
"notifyOnAtMentionOnlyEnabled": false,
"afterGameReviewEnabled": true,
"toastPosition": "BOTTOM_RIGHT",
"toastScreen": 0,
"toastDisplayTime": 5000
,
"themeName": "default",
"lastGameType": "faf",
"localization": ,
"rememberLastTab": true,
"showPasswordProtectedGames": true,
"showModdedGames": true,
"ignoredNotifications": [],
"lastGameMinRating": 800,
"lastGameMaxRating": 1300,
"ladder1v1":
"factions": [
"aeon",
"cybran",
"uef",
"seraphim"
]
,
"news":
"lastReadNewsUrl": "http://direct.faforever.com/2019/03/king-of-badlands-tournament-march-30th/"
,
"developer":
"gameRepositoryUrl": "https://github.com/FAForever/fa.git"
,
"vaultPrefs":
"onlineReplaySortConfig":
"sortProperty": "startTime",
"sortOrder": "DESC"
,
"mapSortConfig":
"sortProperty": "statistics.plays",
"sortOrder": "DESC"
,
"modVaultConfig":
"sortProperty": "latestVersion.createTime",
"sortOrder": "DESC"
,
"gameListSorting": [],
"gameTileSortingOrder": "PLAYER_DES",
"unitDataBaseType": "RACKOVER",
"storedCookies": ,
"lastGameOnlyFriends": false
the only part that matters is "forgedAlliance"
:
"forgedAlliance":
"customMapsDirectory": "/home/t/My Games/Gas Powered Games/Supreme Commander Forged Alliance/Maps",
"preferencesFile": "/home/t/.wine/drive_c/users/t/Application Data/Gas Powered Games/Supreme Commander Forged Alliance/Game.prefs",
"officialMapsDirectory": "/home/t/faf/./Maps",
"modsDirectory": "/home/t/My Games/Gas Powered Games/Supreme Commander Forged Alliance/Mods",
"port": 6112,
"autoDownloadMaps": true,
"executableDecorator": ""%s""
,
I run commands to obtain this :
"forgedAlliance":
"path": "/home/t/.steam/steam/steamapps/common/Supreme Commander Forged Alliance",
"installationPath": "/home/t/.steam/steam/steamapps/common/Supreme Commander Forged Alliance",
"customMapsDirectory": "/home/t/My Games/Gas Powered Games/Supreme Commander Forged Alliance/Maps",
"preferencesFile": "/home/t/.steam/steam/steamapps/compatdata/9420/pfx/drive_c/users/steamuser/Local Settings/Application Data/Gas Powered Games/Supreme Commander Forged Alliance/Game.prefs",
"officialMapsDirectory": "/home/t/faf/./Maps",
"modsDirectory": "/home/t/My Games/Gas Powered Games/Supreme Commander Forged Alliance/Mods",
"port": 6112,
"autoDownloadMaps": true,
"executableDecorator": "/home/t/faf/run "%s""
,
the commands that work (in a standard case where things don't move around) are :
if ! grep -q '"path"' $user_path/.faforever/client.prefs > /dev/null
then
sed -i '12i"path": "'$user_path'/.steam/steam/steamapps/common/Supreme Commander Forged Alliance",' $user_path/.faforever/client.prefs
sed -i '13i"installationPath": "'$user_path'/.steam/steam/steamapps/common/Supreme Commander Forged Alliance",' $user_path/.faforever/client.prefs
fi
! grep -q '"preferencesFile": "'$user_path'/.steam/steam/steamapps/compatdata/9420/pfx/drive_c/users/steamuser/Local Settings/Application Data/Gas Powered Games/Supreme Commander Forged Alliance/Game.prefs",' $user_path/.faforever/client.prefs > /dev/null && sed -i 's_"preferencesFile".*_"preferencesFile": "'$user_path'/.steam/steam/steamapps/compatdata/9420/pfx/drive_c/users/steamuser/Local Settings/Application Data/Gas Powered Games/Supreme Commander Forged Alliance/Game.prefs",_' $user_path/.faforever/client.prefs
! grep -q '"executableDecorator": "'$user_path'/faf/",' $user_path/.faforever/client.prefs > /dev/null && sed -i 's_"executableDecorator".*_"executableDecorator": "'$user_path'/faf/run \"%s\""_' $user_path/.faforever/client.prefs
shell-script shell sed posix
add a comment |
I've googled around a lot for this and it seems there is no precursor to this need.
I need to edit an applications preference file programatically : as part of a shell script.
and the prefs are stored in strict json format : this means the app loading that preference file will crash at startup if there is a comma ,
before a closing curly brace }
.
normally this wouldn't be an issue.
I'd just use my sed
s accordingly : if the line containing my faulty text lines up at the end of a section in my example file, then when replacing this text I will always put it without a comma.
If another line containing another faulty bit I want to replace is not at the end, I always replace it including a comma.
Example :
(I use underscore _
as my sed's delimiter because the stings to replace are full of backslashes sometimes)
sed -i 's_"executableDecorator".*_"executableDecorator": "'$user_path'/faf/run \"%s\"",_' $user_path/.faforever/client.prefs
if that line was at the end :
sed -i 's_"executableDecorator".*_"executableDecorator": "'$user_path'/faf/run \"%s\""_' $user_path/.faforever/client.prefs
this would work, But!...
I have the app end before I run my script so that both aren't editing the preferences at the same time, but even still, because of this app's asynchronous execution the preferences my script will be receiving will differ every time.
it's completely random.
sometimes a line could be in the middle sometimes at the end. The app itself (Java & some json java lib) knows how to append comma or not depending on the context but as part of my shell script... I feel things are going to get bloated.
(If not and there's a shorthand to ensure I have comma or not depending on if next line is }
, then that is a better simpler solution that I would be more interested in)
But as it stands I'm looking for a POSIX utility that fixes json so that I can "sanitize" my json prefs file as soon as I'm done butchering it all within my shell script ...does such a thing exist?
EDIT :
here's the base file (whole file, ) :
"mainWindow":
"width": 800,
"height": 600,
"maximized": false,
"lastView": "NEWS",
"lastChildViews": ,
"x": 67.0,
"y": 27.0
,
"forgedAlliance":
"customMapsDirectory": "/home/t/My Games/Gas Powered Games/Supreme Commander Forged Alliance/Maps",
"preferencesFile": "/home/t/.wine/drive_c/users/t/Application Data/Gas Powered Games/Supreme Commander Forged Alliance/Game.prefs",
"officialMapsDirectory": "/home/t/faf/./Maps",
"modsDirectory": "/home/t/My Games/Gas Powered Games/Supreme Commander Forged Alliance/Mods",
"port": 6112,
"autoDownloadMaps": true,
"executableDecorator": ""%s""
,
"login":
"username": "tatsu",
"password": "*******",
"autoLogin": true
,
"chat":
"zoom": 1.0,
"learnedAutoComplete": false,
"previewImageUrls": true,
"maxMessages": 500,
"chatColorMode": "CUSTOM",
"channelTabScrollPaneWidth": 250,
"userToColor": ,
"hideFoeMessages": true,
"timeFormat": "AUTO",
"chatFormat": "COMPACT",
"idleThreshold": 10
,
"notification":
"soundsEnabled": true,
"transientNotificationsEnabled": true,
"mentionSoundEnabled": true,
"infoSoundEnabled": true,
"warnSoundEnabled": true,
"errorSoundEnabled": true,
"friendOnlineToastEnabled": true,
"friendOfflineToastEnabled": true,
"ladder1v1ToastEnabled": true,
"friendOnlineSoundEnabled": true,
"friendOfflineSoundEnabled": true,
"friendJoinsGameSoundEnabled": true,
"friendPlaysGameSoundEnabled": true,
"friendPlaysGameToastEnabled": true,
"privateMessageSoundEnabled": true,
"privateMessageToastEnabled": true,
"friendJoinsGameToastEnabled": true,
"notifyOnAtMentionOnlyEnabled": false,
"afterGameReviewEnabled": true,
"toastPosition": "BOTTOM_RIGHT",
"toastScreen": 0,
"toastDisplayTime": 5000
,
"themeName": "default",
"lastGameType": "faf",
"localization": ,
"rememberLastTab": true,
"showPasswordProtectedGames": true,
"showModdedGames": true,
"ignoredNotifications": [],
"lastGameMinRating": 800,
"lastGameMaxRating": 1300,
"ladder1v1":
"factions": [
"aeon",
"cybran",
"uef",
"seraphim"
]
,
"news":
"lastReadNewsUrl": "http://direct.faforever.com/2019/03/king-of-badlands-tournament-march-30th/"
,
"developer":
"gameRepositoryUrl": "https://github.com/FAForever/fa.git"
,
"vaultPrefs":
"onlineReplaySortConfig":
"sortProperty": "startTime",
"sortOrder": "DESC"
,
"mapSortConfig":
"sortProperty": "statistics.plays",
"sortOrder": "DESC"
,
"modVaultConfig":
"sortProperty": "latestVersion.createTime",
"sortOrder": "DESC"
,
"gameListSorting": [],
"gameTileSortingOrder": "PLAYER_DES",
"unitDataBaseType": "RACKOVER",
"storedCookies": ,
"lastGameOnlyFriends": false
the only part that matters is "forgedAlliance"
:
"forgedAlliance":
"customMapsDirectory": "/home/t/My Games/Gas Powered Games/Supreme Commander Forged Alliance/Maps",
"preferencesFile": "/home/t/.wine/drive_c/users/t/Application Data/Gas Powered Games/Supreme Commander Forged Alliance/Game.prefs",
"officialMapsDirectory": "/home/t/faf/./Maps",
"modsDirectory": "/home/t/My Games/Gas Powered Games/Supreme Commander Forged Alliance/Mods",
"port": 6112,
"autoDownloadMaps": true,
"executableDecorator": ""%s""
,
I run commands to obtain this :
"forgedAlliance":
"path": "/home/t/.steam/steam/steamapps/common/Supreme Commander Forged Alliance",
"installationPath": "/home/t/.steam/steam/steamapps/common/Supreme Commander Forged Alliance",
"customMapsDirectory": "/home/t/My Games/Gas Powered Games/Supreme Commander Forged Alliance/Maps",
"preferencesFile": "/home/t/.steam/steam/steamapps/compatdata/9420/pfx/drive_c/users/steamuser/Local Settings/Application Data/Gas Powered Games/Supreme Commander Forged Alliance/Game.prefs",
"officialMapsDirectory": "/home/t/faf/./Maps",
"modsDirectory": "/home/t/My Games/Gas Powered Games/Supreme Commander Forged Alliance/Mods",
"port": 6112,
"autoDownloadMaps": true,
"executableDecorator": "/home/t/faf/run "%s""
,
the commands that work (in a standard case where things don't move around) are :
if ! grep -q '"path"' $user_path/.faforever/client.prefs > /dev/null
then
sed -i '12i"path": "'$user_path'/.steam/steam/steamapps/common/Supreme Commander Forged Alliance",' $user_path/.faforever/client.prefs
sed -i '13i"installationPath": "'$user_path'/.steam/steam/steamapps/common/Supreme Commander Forged Alliance",' $user_path/.faforever/client.prefs
fi
! grep -q '"preferencesFile": "'$user_path'/.steam/steam/steamapps/compatdata/9420/pfx/drive_c/users/steamuser/Local Settings/Application Data/Gas Powered Games/Supreme Commander Forged Alliance/Game.prefs",' $user_path/.faforever/client.prefs > /dev/null && sed -i 's_"preferencesFile".*_"preferencesFile": "'$user_path'/.steam/steam/steamapps/compatdata/9420/pfx/drive_c/users/steamuser/Local Settings/Application Data/Gas Powered Games/Supreme Commander Forged Alliance/Game.prefs",_' $user_path/.faforever/client.prefs
! grep -q '"executableDecorator": "'$user_path'/faf/",' $user_path/.faforever/client.prefs > /dev/null && sed -i 's_"executableDecorator".*_"executableDecorator": "'$user_path'/faf/run \"%s\""_' $user_path/.faforever/client.prefs
shell-script shell sed posix
Is there no way at all you could use jq or similar to modify it in the first place instead of text-mangling?
– Michael Homer
2 days ago
surely! what's jq? googling...
– tatsu
2 days ago
In that case, if you could provide a minimal example of the file structure and the changes you'd like to make, someone can probably steer you right.
– Michael Homer
2 days ago
Ok, I added the file, plus the bit I edit, plus the result and also what I used to get there.
– tatsu
2 days ago
add a comment |
I've googled around a lot for this and it seems there is no precursor to this need.
I need to edit an applications preference file programatically : as part of a shell script.
and the prefs are stored in strict json format : this means the app loading that preference file will crash at startup if there is a comma ,
before a closing curly brace }
.
normally this wouldn't be an issue.
I'd just use my sed
s accordingly : if the line containing my faulty text lines up at the end of a section in my example file, then when replacing this text I will always put it without a comma.
If another line containing another faulty bit I want to replace is not at the end, I always replace it including a comma.
Example :
(I use underscore _
as my sed's delimiter because the stings to replace are full of backslashes sometimes)
sed -i 's_"executableDecorator".*_"executableDecorator": "'$user_path'/faf/run \"%s\"",_' $user_path/.faforever/client.prefs
if that line was at the end :
sed -i 's_"executableDecorator".*_"executableDecorator": "'$user_path'/faf/run \"%s\""_' $user_path/.faforever/client.prefs
this would work, But!...
I have the app end before I run my script so that both aren't editing the preferences at the same time, but even still, because of this app's asynchronous execution the preferences my script will be receiving will differ every time.
it's completely random.
sometimes a line could be in the middle sometimes at the end. The app itself (Java & some json java lib) knows how to append comma or not depending on the context but as part of my shell script... I feel things are going to get bloated.
(If not and there's a shorthand to ensure I have comma or not depending on if next line is }
, then that is a better simpler solution that I would be more interested in)
But as it stands I'm looking for a POSIX utility that fixes json so that I can "sanitize" my json prefs file as soon as I'm done butchering it all within my shell script ...does such a thing exist?
EDIT :
here's the base file (whole file, ) :
"mainWindow":
"width": 800,
"height": 600,
"maximized": false,
"lastView": "NEWS",
"lastChildViews": ,
"x": 67.0,
"y": 27.0
,
"forgedAlliance":
"customMapsDirectory": "/home/t/My Games/Gas Powered Games/Supreme Commander Forged Alliance/Maps",
"preferencesFile": "/home/t/.wine/drive_c/users/t/Application Data/Gas Powered Games/Supreme Commander Forged Alliance/Game.prefs",
"officialMapsDirectory": "/home/t/faf/./Maps",
"modsDirectory": "/home/t/My Games/Gas Powered Games/Supreme Commander Forged Alliance/Mods",
"port": 6112,
"autoDownloadMaps": true,
"executableDecorator": ""%s""
,
"login":
"username": "tatsu",
"password": "*******",
"autoLogin": true
,
"chat":
"zoom": 1.0,
"learnedAutoComplete": false,
"previewImageUrls": true,
"maxMessages": 500,
"chatColorMode": "CUSTOM",
"channelTabScrollPaneWidth": 250,
"userToColor": ,
"hideFoeMessages": true,
"timeFormat": "AUTO",
"chatFormat": "COMPACT",
"idleThreshold": 10
,
"notification":
"soundsEnabled": true,
"transientNotificationsEnabled": true,
"mentionSoundEnabled": true,
"infoSoundEnabled": true,
"warnSoundEnabled": true,
"errorSoundEnabled": true,
"friendOnlineToastEnabled": true,
"friendOfflineToastEnabled": true,
"ladder1v1ToastEnabled": true,
"friendOnlineSoundEnabled": true,
"friendOfflineSoundEnabled": true,
"friendJoinsGameSoundEnabled": true,
"friendPlaysGameSoundEnabled": true,
"friendPlaysGameToastEnabled": true,
"privateMessageSoundEnabled": true,
"privateMessageToastEnabled": true,
"friendJoinsGameToastEnabled": true,
"notifyOnAtMentionOnlyEnabled": false,
"afterGameReviewEnabled": true,
"toastPosition": "BOTTOM_RIGHT",
"toastScreen": 0,
"toastDisplayTime": 5000
,
"themeName": "default",
"lastGameType": "faf",
"localization": ,
"rememberLastTab": true,
"showPasswordProtectedGames": true,
"showModdedGames": true,
"ignoredNotifications": [],
"lastGameMinRating": 800,
"lastGameMaxRating": 1300,
"ladder1v1":
"factions": [
"aeon",
"cybran",
"uef",
"seraphim"
]
,
"news":
"lastReadNewsUrl": "http://direct.faforever.com/2019/03/king-of-badlands-tournament-march-30th/"
,
"developer":
"gameRepositoryUrl": "https://github.com/FAForever/fa.git"
,
"vaultPrefs":
"onlineReplaySortConfig":
"sortProperty": "startTime",
"sortOrder": "DESC"
,
"mapSortConfig":
"sortProperty": "statistics.plays",
"sortOrder": "DESC"
,
"modVaultConfig":
"sortProperty": "latestVersion.createTime",
"sortOrder": "DESC"
,
"gameListSorting": [],
"gameTileSortingOrder": "PLAYER_DES",
"unitDataBaseType": "RACKOVER",
"storedCookies": ,
"lastGameOnlyFriends": false
the only part that matters is "forgedAlliance"
:
"forgedAlliance":
"customMapsDirectory": "/home/t/My Games/Gas Powered Games/Supreme Commander Forged Alliance/Maps",
"preferencesFile": "/home/t/.wine/drive_c/users/t/Application Data/Gas Powered Games/Supreme Commander Forged Alliance/Game.prefs",
"officialMapsDirectory": "/home/t/faf/./Maps",
"modsDirectory": "/home/t/My Games/Gas Powered Games/Supreme Commander Forged Alliance/Mods",
"port": 6112,
"autoDownloadMaps": true,
"executableDecorator": ""%s""
,
I run commands to obtain this :
"forgedAlliance":
"path": "/home/t/.steam/steam/steamapps/common/Supreme Commander Forged Alliance",
"installationPath": "/home/t/.steam/steam/steamapps/common/Supreme Commander Forged Alliance",
"customMapsDirectory": "/home/t/My Games/Gas Powered Games/Supreme Commander Forged Alliance/Maps",
"preferencesFile": "/home/t/.steam/steam/steamapps/compatdata/9420/pfx/drive_c/users/steamuser/Local Settings/Application Data/Gas Powered Games/Supreme Commander Forged Alliance/Game.prefs",
"officialMapsDirectory": "/home/t/faf/./Maps",
"modsDirectory": "/home/t/My Games/Gas Powered Games/Supreme Commander Forged Alliance/Mods",
"port": 6112,
"autoDownloadMaps": true,
"executableDecorator": "/home/t/faf/run "%s""
,
the commands that work (in a standard case where things don't move around) are :
if ! grep -q '"path"' $user_path/.faforever/client.prefs > /dev/null
then
sed -i '12i"path": "'$user_path'/.steam/steam/steamapps/common/Supreme Commander Forged Alliance",' $user_path/.faforever/client.prefs
sed -i '13i"installationPath": "'$user_path'/.steam/steam/steamapps/common/Supreme Commander Forged Alliance",' $user_path/.faforever/client.prefs
fi
! grep -q '"preferencesFile": "'$user_path'/.steam/steam/steamapps/compatdata/9420/pfx/drive_c/users/steamuser/Local Settings/Application Data/Gas Powered Games/Supreme Commander Forged Alliance/Game.prefs",' $user_path/.faforever/client.prefs > /dev/null && sed -i 's_"preferencesFile".*_"preferencesFile": "'$user_path'/.steam/steam/steamapps/compatdata/9420/pfx/drive_c/users/steamuser/Local Settings/Application Data/Gas Powered Games/Supreme Commander Forged Alliance/Game.prefs",_' $user_path/.faforever/client.prefs
! grep -q '"executableDecorator": "'$user_path'/faf/",' $user_path/.faforever/client.prefs > /dev/null && sed -i 's_"executableDecorator".*_"executableDecorator": "'$user_path'/faf/run \"%s\""_' $user_path/.faforever/client.prefs
shell-script shell sed posix
I've googled around a lot for this and it seems there is no precursor to this need.
I need to edit an applications preference file programatically : as part of a shell script.
and the prefs are stored in strict json format : this means the app loading that preference file will crash at startup if there is a comma ,
before a closing curly brace }
.
normally this wouldn't be an issue.
I'd just use my sed
s accordingly : if the line containing my faulty text lines up at the end of a section in my example file, then when replacing this text I will always put it without a comma.
If another line containing another faulty bit I want to replace is not at the end, I always replace it including a comma.
Example :
(I use underscore _
as my sed's delimiter because the stings to replace are full of backslashes sometimes)
sed -i 's_"executableDecorator".*_"executableDecorator": "'$user_path'/faf/run \"%s\"",_' $user_path/.faforever/client.prefs
if that line was at the end :
sed -i 's_"executableDecorator".*_"executableDecorator": "'$user_path'/faf/run \"%s\""_' $user_path/.faforever/client.prefs
this would work, But!...
I have the app end before I run my script so that both aren't editing the preferences at the same time, but even still, because of this app's asynchronous execution the preferences my script will be receiving will differ every time.
it's completely random.
sometimes a line could be in the middle sometimes at the end. The app itself (Java & some json java lib) knows how to append comma or not depending on the context but as part of my shell script... I feel things are going to get bloated.
(If not and there's a shorthand to ensure I have comma or not depending on if next line is }
, then that is a better simpler solution that I would be more interested in)
But as it stands I'm looking for a POSIX utility that fixes json so that I can "sanitize" my json prefs file as soon as I'm done butchering it all within my shell script ...does such a thing exist?
EDIT :
here's the base file (whole file, ) :
"mainWindow":
"width": 800,
"height": 600,
"maximized": false,
"lastView": "NEWS",
"lastChildViews": ,
"x": 67.0,
"y": 27.0
,
"forgedAlliance":
"customMapsDirectory": "/home/t/My Games/Gas Powered Games/Supreme Commander Forged Alliance/Maps",
"preferencesFile": "/home/t/.wine/drive_c/users/t/Application Data/Gas Powered Games/Supreme Commander Forged Alliance/Game.prefs",
"officialMapsDirectory": "/home/t/faf/./Maps",
"modsDirectory": "/home/t/My Games/Gas Powered Games/Supreme Commander Forged Alliance/Mods",
"port": 6112,
"autoDownloadMaps": true,
"executableDecorator": ""%s""
,
"login":
"username": "tatsu",
"password": "*******",
"autoLogin": true
,
"chat":
"zoom": 1.0,
"learnedAutoComplete": false,
"previewImageUrls": true,
"maxMessages": 500,
"chatColorMode": "CUSTOM",
"channelTabScrollPaneWidth": 250,
"userToColor": ,
"hideFoeMessages": true,
"timeFormat": "AUTO",
"chatFormat": "COMPACT",
"idleThreshold": 10
,
"notification":
"soundsEnabled": true,
"transientNotificationsEnabled": true,
"mentionSoundEnabled": true,
"infoSoundEnabled": true,
"warnSoundEnabled": true,
"errorSoundEnabled": true,
"friendOnlineToastEnabled": true,
"friendOfflineToastEnabled": true,
"ladder1v1ToastEnabled": true,
"friendOnlineSoundEnabled": true,
"friendOfflineSoundEnabled": true,
"friendJoinsGameSoundEnabled": true,
"friendPlaysGameSoundEnabled": true,
"friendPlaysGameToastEnabled": true,
"privateMessageSoundEnabled": true,
"privateMessageToastEnabled": true,
"friendJoinsGameToastEnabled": true,
"notifyOnAtMentionOnlyEnabled": false,
"afterGameReviewEnabled": true,
"toastPosition": "BOTTOM_RIGHT",
"toastScreen": 0,
"toastDisplayTime": 5000
,
"themeName": "default",
"lastGameType": "faf",
"localization": ,
"rememberLastTab": true,
"showPasswordProtectedGames": true,
"showModdedGames": true,
"ignoredNotifications": [],
"lastGameMinRating": 800,
"lastGameMaxRating": 1300,
"ladder1v1":
"factions": [
"aeon",
"cybran",
"uef",
"seraphim"
]
,
"news":
"lastReadNewsUrl": "http://direct.faforever.com/2019/03/king-of-badlands-tournament-march-30th/"
,
"developer":
"gameRepositoryUrl": "https://github.com/FAForever/fa.git"
,
"vaultPrefs":
"onlineReplaySortConfig":
"sortProperty": "startTime",
"sortOrder": "DESC"
,
"mapSortConfig":
"sortProperty": "statistics.plays",
"sortOrder": "DESC"
,
"modVaultConfig":
"sortProperty": "latestVersion.createTime",
"sortOrder": "DESC"
,
"gameListSorting": [],
"gameTileSortingOrder": "PLAYER_DES",
"unitDataBaseType": "RACKOVER",
"storedCookies": ,
"lastGameOnlyFriends": false
the only part that matters is "forgedAlliance"
:
"forgedAlliance":
"customMapsDirectory": "/home/t/My Games/Gas Powered Games/Supreme Commander Forged Alliance/Maps",
"preferencesFile": "/home/t/.wine/drive_c/users/t/Application Data/Gas Powered Games/Supreme Commander Forged Alliance/Game.prefs",
"officialMapsDirectory": "/home/t/faf/./Maps",
"modsDirectory": "/home/t/My Games/Gas Powered Games/Supreme Commander Forged Alliance/Mods",
"port": 6112,
"autoDownloadMaps": true,
"executableDecorator": ""%s""
,
I run commands to obtain this :
"forgedAlliance":
"path": "/home/t/.steam/steam/steamapps/common/Supreme Commander Forged Alliance",
"installationPath": "/home/t/.steam/steam/steamapps/common/Supreme Commander Forged Alliance",
"customMapsDirectory": "/home/t/My Games/Gas Powered Games/Supreme Commander Forged Alliance/Maps",
"preferencesFile": "/home/t/.steam/steam/steamapps/compatdata/9420/pfx/drive_c/users/steamuser/Local Settings/Application Data/Gas Powered Games/Supreme Commander Forged Alliance/Game.prefs",
"officialMapsDirectory": "/home/t/faf/./Maps",
"modsDirectory": "/home/t/My Games/Gas Powered Games/Supreme Commander Forged Alliance/Mods",
"port": 6112,
"autoDownloadMaps": true,
"executableDecorator": "/home/t/faf/run "%s""
,
the commands that work (in a standard case where things don't move around) are :
if ! grep -q '"path"' $user_path/.faforever/client.prefs > /dev/null
then
sed -i '12i"path": "'$user_path'/.steam/steam/steamapps/common/Supreme Commander Forged Alliance",' $user_path/.faforever/client.prefs
sed -i '13i"installationPath": "'$user_path'/.steam/steam/steamapps/common/Supreme Commander Forged Alliance",' $user_path/.faforever/client.prefs
fi
! grep -q '"preferencesFile": "'$user_path'/.steam/steam/steamapps/compatdata/9420/pfx/drive_c/users/steamuser/Local Settings/Application Data/Gas Powered Games/Supreme Commander Forged Alliance/Game.prefs",' $user_path/.faforever/client.prefs > /dev/null && sed -i 's_"preferencesFile".*_"preferencesFile": "'$user_path'/.steam/steam/steamapps/compatdata/9420/pfx/drive_c/users/steamuser/Local Settings/Application Data/Gas Powered Games/Supreme Commander Forged Alliance/Game.prefs",_' $user_path/.faforever/client.prefs
! grep -q '"executableDecorator": "'$user_path'/faf/",' $user_path/.faforever/client.prefs > /dev/null && sed -i 's_"executableDecorator".*_"executableDecorator": "'$user_path'/faf/run \"%s\""_' $user_path/.faforever/client.prefs
shell-script shell sed posix
shell-script shell sed posix
edited 2 days ago
tatsu
asked 2 days ago
tatsutatsu
1187
1187
Is there no way at all you could use jq or similar to modify it in the first place instead of text-mangling?
– Michael Homer
2 days ago
surely! what's jq? googling...
– tatsu
2 days ago
In that case, if you could provide a minimal example of the file structure and the changes you'd like to make, someone can probably steer you right.
– Michael Homer
2 days ago
Ok, I added the file, plus the bit I edit, plus the result and also what I used to get there.
– tatsu
2 days ago
add a comment |
Is there no way at all you could use jq or similar to modify it in the first place instead of text-mangling?
– Michael Homer
2 days ago
surely! what's jq? googling...
– tatsu
2 days ago
In that case, if you could provide a minimal example of the file structure and the changes you'd like to make, someone can probably steer you right.
– Michael Homer
2 days ago
Ok, I added the file, plus the bit I edit, plus the result and also what I used to get there.
– tatsu
2 days ago
Is there no way at all you could use jq or similar to modify it in the first place instead of text-mangling?
– Michael Homer
2 days ago
Is there no way at all you could use jq or similar to modify it in the first place instead of text-mangling?
– Michael Homer
2 days ago
surely! what's jq? googling...
– tatsu
2 days ago
surely! what's jq? googling...
– tatsu
2 days ago
In that case, if you could provide a minimal example of the file structure and the changes you'd like to make, someone can probably steer you right.
– Michael Homer
2 days ago
In that case, if you could provide a minimal example of the file structure and the changes you'd like to make, someone can probably steer you right.
– Michael Homer
2 days ago
Ok, I added the file, plus the bit I edit, plus the result and also what I used to get there.
– tatsu
2 days ago
Ok, I added the file, plus the bit I edit, plus the result and also what I used to get there.
– tatsu
2 days ago
add a comment |
1 Answer
1
active
oldest
votes
This jq command will make exactly those changes:
jq --arg user_path "$user_path" '
.forgedAlliance +=
installationPath: ($user_path + "/.steam/steam/steamapps/common/Supreme Commander Forged Alliance"),
path: ($user_path + "/.steam/steam/steamapps/common/Supreme Commander Forged Alliance"),
preferencesFile: ($user_path + "/.steam/steam/steamapps/compatdata/9420/pfx/drive_c/users/steamuser/Local Settings/Application Data/Gas Powered Games/Supreme Commander Forged Alliance/Game.prefs"),
executableDecorator: ($user_path + "/faf/run "%s"")
'
This uses
--arg user_path "$user_path"
to bring the shell variable into the jq program (you could also use the variable binding operator"'"$user_path"'" as $user_path |
, but it would involve ugly quote splicing)- Update-assignment
.forgedAlliance +=
to process the whole file, updating just the value of the "forgedAlliance" key by merging it with what's on the right. - A fresh object constructed from
to
with just the new key values you wanted computed inside it. If there are existing keys with the same name, they will be replaced.
$user_path
to access that variable binding we made above.
The whitespace is optional - it's just there to make it easier to read on this site.
jq always outputs as valid JSON, so you don't have any comma cleanup to do. You may find the sponge
command from moreutils useful for updating the file itself, because there is no -i
equivalent in jq, but you can also just redirect to another file
jq ... > tmpfile
mv tmpfile prefs.json
and step around it manually as well.
There is one (slight?) difference to what your code did: you made no changes for path
and installationPath
if "path" appeared anywhere in the file. There's no way to replicate that with jq directly, but you could split the command in two (one for path, one for all the time) if there's a necessary semantic element to that. This command will always make the change, but if it's already got the same value for a key that doesn't have any effect.
If this is a fixed set of replacements, you could also make a file with just the object from point 3 above in it literally (as true JSON, not dynamically computed), and then use
jq --slurpfile tmp rhs.json '.forgedAlliance += tmp[0]'
with the same effect as the big command above.
"you made no changes forpath
andinstallationPath
if "path" appeared anywhere in the file.", well looking back on that that's terrible. I prefer your approach. it does mean installing jq will have to become part of the script but maybe that's a manageable sacrifice.
– tatsu
2 days ago
add a comment |
Your Answer
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "106"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f509764%2freshaping-json-reparing-json-inside-shell-script-remove-trailing-comma%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
This jq command will make exactly those changes:
jq --arg user_path "$user_path" '
.forgedAlliance +=
installationPath: ($user_path + "/.steam/steam/steamapps/common/Supreme Commander Forged Alliance"),
path: ($user_path + "/.steam/steam/steamapps/common/Supreme Commander Forged Alliance"),
preferencesFile: ($user_path + "/.steam/steam/steamapps/compatdata/9420/pfx/drive_c/users/steamuser/Local Settings/Application Data/Gas Powered Games/Supreme Commander Forged Alliance/Game.prefs"),
executableDecorator: ($user_path + "/faf/run "%s"")
'
This uses
--arg user_path "$user_path"
to bring the shell variable into the jq program (you could also use the variable binding operator"'"$user_path"'" as $user_path |
, but it would involve ugly quote splicing)- Update-assignment
.forgedAlliance +=
to process the whole file, updating just the value of the "forgedAlliance" key by merging it with what's on the right. - A fresh object constructed from
to
with just the new key values you wanted computed inside it. If there are existing keys with the same name, they will be replaced.
$user_path
to access that variable binding we made above.
The whitespace is optional - it's just there to make it easier to read on this site.
jq always outputs as valid JSON, so you don't have any comma cleanup to do. You may find the sponge
command from moreutils useful for updating the file itself, because there is no -i
equivalent in jq, but you can also just redirect to another file
jq ... > tmpfile
mv tmpfile prefs.json
and step around it manually as well.
There is one (slight?) difference to what your code did: you made no changes for path
and installationPath
if "path" appeared anywhere in the file. There's no way to replicate that with jq directly, but you could split the command in two (one for path, one for all the time) if there's a necessary semantic element to that. This command will always make the change, but if it's already got the same value for a key that doesn't have any effect.
If this is a fixed set of replacements, you could also make a file with just the object from point 3 above in it literally (as true JSON, not dynamically computed), and then use
jq --slurpfile tmp rhs.json '.forgedAlliance += tmp[0]'
with the same effect as the big command above.
"you made no changes forpath
andinstallationPath
if "path" appeared anywhere in the file.", well looking back on that that's terrible. I prefer your approach. it does mean installing jq will have to become part of the script but maybe that's a manageable sacrifice.
– tatsu
2 days ago
add a comment |
This jq command will make exactly those changes:
jq --arg user_path "$user_path" '
.forgedAlliance +=
installationPath: ($user_path + "/.steam/steam/steamapps/common/Supreme Commander Forged Alliance"),
path: ($user_path + "/.steam/steam/steamapps/common/Supreme Commander Forged Alliance"),
preferencesFile: ($user_path + "/.steam/steam/steamapps/compatdata/9420/pfx/drive_c/users/steamuser/Local Settings/Application Data/Gas Powered Games/Supreme Commander Forged Alliance/Game.prefs"),
executableDecorator: ($user_path + "/faf/run "%s"")
'
This uses
--arg user_path "$user_path"
to bring the shell variable into the jq program (you could also use the variable binding operator"'"$user_path"'" as $user_path |
, but it would involve ugly quote splicing)- Update-assignment
.forgedAlliance +=
to process the whole file, updating just the value of the "forgedAlliance" key by merging it with what's on the right. - A fresh object constructed from
to
with just the new key values you wanted computed inside it. If there are existing keys with the same name, they will be replaced.
$user_path
to access that variable binding we made above.
The whitespace is optional - it's just there to make it easier to read on this site.
jq always outputs as valid JSON, so you don't have any comma cleanup to do. You may find the sponge
command from moreutils useful for updating the file itself, because there is no -i
equivalent in jq, but you can also just redirect to another file
jq ... > tmpfile
mv tmpfile prefs.json
and step around it manually as well.
There is one (slight?) difference to what your code did: you made no changes for path
and installationPath
if "path" appeared anywhere in the file. There's no way to replicate that with jq directly, but you could split the command in two (one for path, one for all the time) if there's a necessary semantic element to that. This command will always make the change, but if it's already got the same value for a key that doesn't have any effect.
If this is a fixed set of replacements, you could also make a file with just the object from point 3 above in it literally (as true JSON, not dynamically computed), and then use
jq --slurpfile tmp rhs.json '.forgedAlliance += tmp[0]'
with the same effect as the big command above.
"you made no changes forpath
andinstallationPath
if "path" appeared anywhere in the file.", well looking back on that that's terrible. I prefer your approach. it does mean installing jq will have to become part of the script but maybe that's a manageable sacrifice.
– tatsu
2 days ago
add a comment |
This jq command will make exactly those changes:
jq --arg user_path "$user_path" '
.forgedAlliance +=
installationPath: ($user_path + "/.steam/steam/steamapps/common/Supreme Commander Forged Alliance"),
path: ($user_path + "/.steam/steam/steamapps/common/Supreme Commander Forged Alliance"),
preferencesFile: ($user_path + "/.steam/steam/steamapps/compatdata/9420/pfx/drive_c/users/steamuser/Local Settings/Application Data/Gas Powered Games/Supreme Commander Forged Alliance/Game.prefs"),
executableDecorator: ($user_path + "/faf/run "%s"")
'
This uses
--arg user_path "$user_path"
to bring the shell variable into the jq program (you could also use the variable binding operator"'"$user_path"'" as $user_path |
, but it would involve ugly quote splicing)- Update-assignment
.forgedAlliance +=
to process the whole file, updating just the value of the "forgedAlliance" key by merging it with what's on the right. - A fresh object constructed from
to
with just the new key values you wanted computed inside it. If there are existing keys with the same name, they will be replaced.
$user_path
to access that variable binding we made above.
The whitespace is optional - it's just there to make it easier to read on this site.
jq always outputs as valid JSON, so you don't have any comma cleanup to do. You may find the sponge
command from moreutils useful for updating the file itself, because there is no -i
equivalent in jq, but you can also just redirect to another file
jq ... > tmpfile
mv tmpfile prefs.json
and step around it manually as well.
There is one (slight?) difference to what your code did: you made no changes for path
and installationPath
if "path" appeared anywhere in the file. There's no way to replicate that with jq directly, but you could split the command in two (one for path, one for all the time) if there's a necessary semantic element to that. This command will always make the change, but if it's already got the same value for a key that doesn't have any effect.
If this is a fixed set of replacements, you could also make a file with just the object from point 3 above in it literally (as true JSON, not dynamically computed), and then use
jq --slurpfile tmp rhs.json '.forgedAlliance += tmp[0]'
with the same effect as the big command above.
This jq command will make exactly those changes:
jq --arg user_path "$user_path" '
.forgedAlliance +=
installationPath: ($user_path + "/.steam/steam/steamapps/common/Supreme Commander Forged Alliance"),
path: ($user_path + "/.steam/steam/steamapps/common/Supreme Commander Forged Alliance"),
preferencesFile: ($user_path + "/.steam/steam/steamapps/compatdata/9420/pfx/drive_c/users/steamuser/Local Settings/Application Data/Gas Powered Games/Supreme Commander Forged Alliance/Game.prefs"),
executableDecorator: ($user_path + "/faf/run "%s"")
'
This uses
--arg user_path "$user_path"
to bring the shell variable into the jq program (you could also use the variable binding operator"'"$user_path"'" as $user_path |
, but it would involve ugly quote splicing)- Update-assignment
.forgedAlliance +=
to process the whole file, updating just the value of the "forgedAlliance" key by merging it with what's on the right. - A fresh object constructed from
to
with just the new key values you wanted computed inside it. If there are existing keys with the same name, they will be replaced.
$user_path
to access that variable binding we made above.
The whitespace is optional - it's just there to make it easier to read on this site.
jq always outputs as valid JSON, so you don't have any comma cleanup to do. You may find the sponge
command from moreutils useful for updating the file itself, because there is no -i
equivalent in jq, but you can also just redirect to another file
jq ... > tmpfile
mv tmpfile prefs.json
and step around it manually as well.
There is one (slight?) difference to what your code did: you made no changes for path
and installationPath
if "path" appeared anywhere in the file. There's no way to replicate that with jq directly, but you could split the command in two (one for path, one for all the time) if there's a necessary semantic element to that. This command will always make the change, but if it's already got the same value for a key that doesn't have any effect.
If this is a fixed set of replacements, you could also make a file with just the object from point 3 above in it literally (as true JSON, not dynamically computed), and then use
jq --slurpfile tmp rhs.json '.forgedAlliance += tmp[0]'
with the same effect as the big command above.
answered 2 days ago
Michael HomerMichael Homer
50.5k8140177
50.5k8140177
"you made no changes forpath
andinstallationPath
if "path" appeared anywhere in the file.", well looking back on that that's terrible. I prefer your approach. it does mean installing jq will have to become part of the script but maybe that's a manageable sacrifice.
– tatsu
2 days ago
add a comment |
"you made no changes forpath
andinstallationPath
if "path" appeared anywhere in the file.", well looking back on that that's terrible. I prefer your approach. it does mean installing jq will have to become part of the script but maybe that's a manageable sacrifice.
– tatsu
2 days ago
"you made no changes for
path
and installationPath
if "path" appeared anywhere in the file.", well looking back on that that's terrible. I prefer your approach. it does mean installing jq will have to become part of the script but maybe that's a manageable sacrifice.– tatsu
2 days ago
"you made no changes for
path
and installationPath
if "path" appeared anywhere in the file.", well looking back on that that's terrible. I prefer your approach. it does mean installing jq will have to become part of the script but maybe that's a manageable sacrifice.– tatsu
2 days ago
add a comment |
Thanks for contributing an answer to Unix & Linux Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f509764%2freshaping-json-reparing-json-inside-shell-script-remove-trailing-comma%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Is there no way at all you could use jq or similar to modify it in the first place instead of text-mangling?
– Michael Homer
2 days ago
surely! what's jq? googling...
– tatsu
2 days ago
In that case, if you could provide a minimal example of the file structure and the changes you'd like to make, someone can probably steer you right.
– Michael Homer
2 days ago
Ok, I added the file, plus the bit I edit, plus the result and also what I used to get there.
– tatsu
2 days ago