Zan*_*nna 9 command-line bash scripts sed
我正在处理这个 SE 数据查询的.csv
输出,它看起来像这样(只有 5022 个条目):
"{
""id"": 281952,
""title"": ""Flash 11.2 No Longer Supported by Google Play""
}"
"{
""id"": 281993,
""title"": ""Netbeans won't open in Ubuntu""
}"
Run Code Online (Sandbox Code Playgroud)
(并且它^M
在 [number] 和 ""title"" 之间有行结尾)。我需要它看起来像这样:
281952,Flash 11.2 No Longer Supported by Google Play
281993,Netbeans won't open in Ubuntu
Run Code Online (Sandbox Code Playgroud)
我在某个文本编辑器中修复了这个问题,该编辑器将很容易保持无名,但我想制作一个脚本,这样每次刷新查询时我都不必再次执行此操作,以便其他人可以使用它。我用sed
...
这一系列命令完美运行(虽然它很可能效率低下;它只是一个反复试验的解决方案):
# Print the ^M and remove them, write to a new file:
cat -v QueryR* | sed 's/\^M//' > QueryNew
# remove all the other junk:
sed -i 's/{//' QueryNew
sed -i 's/}//' QueryNew
sed -i 's/""//g' QueryNew
sed -i 's/^"//' QueryNew
sed -i '/,/{N;/\n.*title:\s/{s/,\n.*title:\s/,\ /}}' QueryNew
sed -i 's/^\s\+//' QueryNew
sed -i '/^\s*$/d' QueryNew
sed -i 's/^id:\ //' QueryNew
sed -i 's/,\ /,/' QueryNew
sed -i 's/\\//g' QueryNew
Run Code Online (Sandbox Code Playgroud)
那么,为什么不呢?只有^M
和{}
被删除了,其他一切都还在。
#!/bin/bash
cat -v QueryR* | sed 's/\^M//' > QueryNew
sed -i '{
s/{//
s/}//
s/""//g
s/^"//
/,/{N;/\n.*title:\s/{s/,\n.*title:\s/,\ /}}
s/^\s\+//
/^\s*$/d
s/^id:\ //
s/,\ /,/
s/\\//g
}' QueryNew
Run Code Online (Sandbox Code Playgroud)
我确定我的错误非常明显......
ste*_*ver 11
使用cat -v
将 CR 字符转换为文字^M
序列对我来说从根本上来说似乎很难看 - 如果您需要删除 DOS 行结尾,请使用dos2unix
, tr
, 或sed 's/\r$//
'
如果你坚持使用 sed,那么我建议你打印你想要的位,而不是试图删除所有你不想要的随机位 - 例如
$ sed -rn -e 's/\"//g' -e 's/(.*): (.*)\r/\2/p' QueryR | paste -d '' - -
281952,Flash 11.2 No Longer Supported by Google Play
281993,Netbeans won't open in Ubuntu
Run Code Online (Sandbox Code Playgroud)
您可以通过在值序列的每一端匹配零个或多个引号,将引号删除滚动到键值提取中
$ sed -rn 's/(.*): \"*([^"]*)\"*\r/\2/p' QueryR | paste -d '' - -
281952,Flash 11.2 No Longer Supported by Google Play
281993,Netbeans won't open in Ubuntu
Run Code Online (Sandbox Code Playgroud)
你可以得到真正的花哨和仿效的paste
在sed
通过第一连接线对,\r$
结束,然后乘以相匹配的键值对(g
)和非贪婪
$ sed -rn '/,\r$/ {N; s/([^:]*): \"*([^:"]*)\"*\r\n?/\2/gp}' QueryR
281952,Flash 11.2 No Longer Supported by Google Play
281993,Netbeans won't open in Ubuntu
Run Code Online (Sandbox Code Playgroud)
(我个人更喜欢 KISS 方法并使用第一种方法)。
FWIW,由于您的输入似乎被高估了 JSON,我建议安装适当的 JSON 解析器,例如 jq
sudo apt-get install jq
Run Code Online (Sandbox Code Playgroud)
然后你可以做类似的事情
$ sed -e 's/["]["]/"/g' -e 's/"{/{/' -e 's/}"/}/' QueryR | jq '.id, .title' | paste -d, - -
281952,"Flash 11.2 No Longer Supported by Google Play"
281993,"Netbeans won't open in Ubuntu"
Run Code Online (Sandbox Code Playgroud)
它删除了多余的引号,然后用于jq
提取感兴趣的字段 - 请注意,它jq
似乎处理了 DOS 样式的行结尾,因此无需采取特殊步骤来删除它们。
更改为jq '.[]'
转储所有属性值对。
jq
从使用 grep -o 克服换行符中
获得灵感和基本语法的功劳
由于 steeldriver 和进一步的修补,我修复了它。未精制但有效。
sed '{
s/"{//
s/}"//
s/^"//
/,\r/{N;/\n.*title.*:\s/{s/,\r\n.*title.*:\s/,/}}
s/""//g
s/^\s\+//
/^\s*$/d
s/^id:\ //
s/\\//g
}' QueryR* | tee "$1"
Run Code Online (Sandbox Code Playgroud)
翻译:
s/"{//
删除"{
s/}"//
删除}"
s/^"//
删除"
从行首
/,\r/{N;/\n.*title.*:\s/{s/,\r\n.*title.*:\s/,\ /}}
匹配,\r
在一行和[whatever]title[whatever]:
下一行,替换所有以,
s/""//g
删除所有剩余的双重双引号
s/^\s\+//
从行开始删除空格
/^\s*$/d
删除空行
s/^id:\ //
删除id:
和空间后,
s/\\//g
对于删除反斜杠(转义字符" 添加到一些标题字段)
tee "$1"
在运行脚本时指定一个输出文件,例如./queryclean newquery.csv