Mic*_*lls 3 bash sed text-processing
我创建了一行如下所示的文本:
INSERT INTO radcheck(id, username, attribute, op, value) VALUES (,,00:23:32:c2:a9:e8,Auth-Type,:=,Accept);
Run Code Online (Sandbox Code Playgroud)
我想用 sed 使它看起来像这样:
INSERT INTO radcheck(id, username, attribute, op, value) VALUES (,'','00:23:32:c2:a9:e8','Auth-Type',':=','Accept');
Run Code Online (Sandbox Code Playgroud)
这在上下文中更有意义,并且在过去(显然)17 小时内,我已经深入了解了它:
#!/bin/bash
ssh ubnt@xxx.xxx.xxx.xxx brmacs >>MACS.txt mv MACS.txt /etc/persistent scp mhalls@xxx.xxx.xxx.xxx:/etc/persistent/MACS.txt MACS.txt
sed -i "1d" MACS.txt
head -c 58 MACS.txt >>shortmacs.txt
tail -c 18 shortmacs.txt >>usermac.txt
sed 's/"//g' usermac.txt >>usermacrdy.txt
sed -i 's/^/INSERT INTO `radcheck`(`id`, `username`, `attribute`, `op`, `value`) VALUES (,'',/' usermacrdy.txt
sed "s/$/','Auth-Type',':=','Accept');/" usermacrdy.txt > sqlquery.txt
sed -i "s/,,/\,\'\',\'/" sqlquery.txt
rm -f MACS.txt
rm -f shortmacs.txt
rm -f usermac.txt
rm -f usermacrdy.txt
Run Code Online (Sandbox Code Playgroud)
作品!!!
头部和尾部从 UBNT CPE 设备传输过来的原始文本文件中切出 MAC 地址,然后我通过 sed 传递它以围绕 MAC 地址构建 SQL 语法。
毕竟,我发现id查询的部分不是成功所必需的,所以现在我与以下情况略有相同:
sed -i 's/^/INSERT INTO `radcheck`(`username`, `attribute`, `op`, `value`) VALUES (/' usermacrdy.txt
sed "s/$/','Auth-Type',':=','Accept');/" usermacrdy.txt > sqlquery.txt
sed -i "s/\,\'\',\'//" sqlquery.txt
Run Code Online (Sandbox Code Playgroud)
有四种方法可以包含您需要的单引号。
不能在单引号字符串中转义单引号字符串。但是,可以结束带引号的字符串,插入转义的单引号,然后开始新的单引号字符串。因此,要将单引号放在 中间'ab',请使用:'a'\''b'。或者,使用您需要的 sed 命令:
$ sed -r 's/,([^ ),]+)/,'\''\1'\''/g; s/,,/,'\'\'',/g' file
INSERT INTO radcheck(id, username, attribute, op, value) VALUES (,'','00:23:32:c2:a9:e8','Auth-Type',':=','Accept');
Run Code Online (Sandbox Code Playgroud)
第二种方法是使用双引号字符串,在这种情况下可以轻松插入单引号:
$ sed -r "s/,([^ ),]+)/,'\1'/g; s/,,/,'',/g" file
INSERT INTO radcheck(id, username, attribute, op, value) VALUES (,'','00:23:32:c2:a9:e8','Auth-Type',':=','Accept');
Run Code Online (Sandbox Code Playgroud)
双引号字符串的这个问题是 shell 对它们进行处理。但是,这里没有可激活 shell 的字符,因此很容易。
第三种方法是使用 PM2Ring 演示的十六进制转义。
Jonathan Leffler 在评论中建议的第四种方法是将sed命令放在单独的文件中:
$ cat script.sed
s/,([^ ),]+)/,'\1'/g
s/,,/,'',/g
$ sed -rf script.sed file
INSERT INTO radcheck(id, username, attribute, op, value) VALUES (,'','00:23:32:c2:a9:e8','Auth-Type',':=','Accept');
Run Code Online (Sandbox Code Playgroud)
这种方式具有强大的优势,可以sed直接读取命令,不受shell 的任何干扰。因此,这完全避免了转义 shell 活动字符的需要,并允许以纯sed语法输入命令。
sed解决工作诀窍是将单引号放在您想要的逗号分隔字符串周围,但不要放在其他字符串周围。根据您提供的单个示例,这是一种方法:
s/,([^ ),]+)/,'\1'/g
这将查找一个或多个跟在逗号后面的非空格、非逗号和非关闭括号字符。这些字符放在单引号内。
s/,,/,'',/g
这会查找连续的逗号并在它们之间放置两个单引号。
为了避免额外的反斜杠,上述sed表达式使用了扩展的正则表达式。在 GNU 中,它们被调用为,-r但是,在 BSD 中,它们被调用为-E. 此外,一些非 GNUsed不接受用分号分隔的多个命令。因此,在 OSX 上,尝试:
sed -E -e "s/,([^ ),]+)/,'\1'/g" -e "s/,,/,'',/g" file
Run Code Online (Sandbox Code Playgroud)
从评论中,我们有以下输入;
$ cat file3
INSERT INTO radcheck(username, attribute, op, value) VALUES (00:23:32:c2:a9:e8,'Auth-Type',':=','Accept');
Run Code Online (Sandbox Code Playgroud)
而且,我们想在开放括号后面的 MAC 地址周围加上单引号。要做到这一点:
$ sed -r "s/\(([[:xdigit:]:]+)/('\1'/" file3
INSERT INTO radcheck(username, attribute, op, value) VALUES ('00:23:32:c2:a9:e8','Auth-Type',':=','Accept');
Run Code Online (Sandbox Code Playgroud)
在任何语言环境中,[:xdigit:]将匹配任何十六进制数字。因此,([[:xdigit:]:]+)将匹配一个 MAC 地址(十六进制数字或冒号)。