给定输入文件:
col1 as 'prod 1', col3 as 'prod 2', col9 as 'prod type 2'
需要删除引号并用_替换引号内的空格。我们可以用awk或sed来做吗?
期望的输出:
col1 as prod_1, col3 as prod_2, col9 as prod_type_2
答案 0 :(得分:2)
简单易用的awk
解决方案:
awk -v RS="'" -v ORS='' 'NR%2==0{gsub(" ","_")}1'
将记录分隔符设置为单引号,然后替换每个第二条记录中的空格(即单引号之间的空格)。
允许在单引号字符串中使用换行符,并且不会修改它们。如果要替换所有空格,可以更改gsub
调用以使用简单的正则表达式:
awk -v RS="'" -v ORS='' 'NR%2==0{gsub(/[[:space:]]+/,"_")}1'
例如:
$ awk -v RS="'" -v ORS='' 'NR%2==0{gsub(/[[:space:]]+/,"_")}1' <<<"
> col1 as 'prod 1', col3 as 'prod
> 2', col9 as 'prod type 2'
> "
col1 as prod_1, col3 as prod_2, col9 as prod_type_2
答案 1 :(得分:1)
sed
解决方案:
如果您可以假设引用的字符串没有前导空格,那么这样做:
sed ":a; s/\('[^,][^' \\t]*\)\s/\1_/; ta" my_file
如果您还需要在字符串中容纳前导空格,那么这样做:
sed -e "s/\s*$//" \
-e ":a; s/\('[^,][^' \\t]*\)\s/\1_/; ta" \
-e "s/' /'_/; ta" \
my_file
后者还具有修剪拖尾空白的副作用;如果有必要,可以以更复杂的命令为代价来避免这种情况。
这两个假设字符串的结尾'
与任何后续逗号(,
)之间不会有空格。
这两个都必须处理sed
的替换行为:即使g
命令被赋予s
选项,也不会考虑跳过或转贴一次的文本通过相同的s
命令进一步匹配。这就产生了将字符串中的空白与外部空白区分开来的问题。这些sed
命令通过使用标签(:a
)和条件分支(ta
来解决这个问题,其中t
是命令,a
是目标标签)无论何时进行替换,都要从头开始重新运行整个替换命令。
答案 2 :(得分:1)
使用GNU awk进行多字符RS
,RT
和\s
:
$ awk -v RS="'[^']+'" '{gsub(/\s/,"_",RT); ORS=RT}1' file
col1 as 'prod_1', col3 as 'prod_2', col9 as 'prod_type_2'
鉴于删除封闭引号的新要求:
$ awk -v RS="'[^']+'" '{gsub(/\s/,"_",RT); gsub(/\047/,"",RT); ORS=RT}1' file
col1 as prod_1, col3 as prod_2, col9 as prod_type_2
或者如果您愿意:
$ awk -v RS="'[^']+'" '{gsub(/\s/,"_",RT); ORS=substr(RT,2,length(RT)-2)}1' file
col1 as prod_1, col3 as prod_2, col9 as prod_type_2
答案 3 :(得分:0)
echo "col1 as 'prod 1', col3 as 'prod 2', col9 as 'prod type 2'" | \
awk -F"'" 'BEGIN{OFS=""}{for(i=2;i<NF;i+=2)gsub(" ","_",$i)}1'
col1 as prod_1, col3 as prod_2, col9 as prod_type_2
<强>解释强>
-F"'"
将 f 字段分隔符设置为'
,将每个输入行拆分为字段以'
分隔$1="col1 as "
,$2="prod 1"
,$3=" col3 as "
,...)BEGIN{OFS=""}
设置 o 输出 f ield s eparator 到空字符串,有效删除所有'
s。for(i=2;i<NF;i+=2)
会在{strong> n 的 f 之前对所有偶数进行迭代i
ields gsub(" ","_",$i)
用i
替换字段 _
中的所有空格。1
只会打印(修改过的)行 编辑: 此方法的一个缺点(?)/功能是它按行分割,因此单引号部分不能跨越多行。如果这是一个问题,将'
拆分为记录而不是字段将是解决方案(如rici&#39; s answer):
echo "col1 as 'prod 1', col3 as 'prod 2', col9 as 'prod type 2'" | \
awk -F\ -v RS="'" -v ORS='' -v OFS='_' '!(NR%2){$1=$1}1
col1 as prod_1, col3 as prod_2, col9 as prod_type_2
<强>解释强>
-v RS="'"
将 r ecord s eparator 设置为'
分割输入记录以'
s(而非行)分隔-F\
将 f 字段分隔符设置为
,拆分每个输入记录 into fields 以
分隔$1="col1 as "
,$2="prod 1"
,$3=" col3 as "
,...)-v ORS=''
设置 o 输出 r ecord s eparator 到空字符串,有效删除所有'
s -v OFS='_'
设置 o 输出 f ield s eparator 到_
,在修改后的(!)行中有效地用_
s 替换空格 !(NR%2)
相当于NR%2==0
,并测试当前记录(由 n 标识 r ecords )是一个奇怪的(%
是模运算符){$1=$1}
自行分配第一个字段,标记当前记录已修改(即使它实际上没有改变),有效地替换所有奇数记录中的_
个空格({em>即<{1}}之间的文本 '
只会打印每个记录 答案 4 :(得分:0)
使用gnu-awk:
str="col1 as 'prod 1', col3 as 'prod 2', col9 as 'prod type 2'"
awk -v sq="'" -v re="'[^']*'" -v FPAT="'[^']*'|[^']*" '{
for(i=1; i<=NF; i++) if ($i ~ re) {
gsub(/[[:blank:]]/, "_", $i);
gsub(sq, "", $i)
}
} 1' OFS= <<< "$str"
<强>输出:强>
col1 as prod_1, col3 as prod_2, col9 as prod_type_2