我正在努力解决一个过滤器,我试图在第 3 次或第 n 次出现字符后修剪 CSV 特定列中的数据\
。
我的数据看起来像这样:
data,data,c:\path1\folder2\folder3\folder4\...,data,data,data
data,data,c:\path1\folder2\folder3\folder4\...,data,data,data
data,data,c:\path1\folder2\folder3\folder4\...,data,data,data
data,data,c:\path1\folder2\folder3\folder4\...,data,data,data
我希望过滤器产生:
data,data,c:\path1\folder2\folder3\,data,data,data
第三列包含一个文件路径,它可以是从一个文件夹到多个文件夹的任何位置。我希望最多有 3 个文件夹。
我不想删除其他剩余的列,而是就地编辑文件。
我一直在尝试awk
、sed
、 并尝试将cut
命令组合cut -f1-4 -d '\'
成一个awk
语句,但我一生都无法让它发挥作用。
答案1
使用 GNU awk 执行 gensub():
$ awk -v n=3 'BEGIN{FS=OFS=","} {$3=gensub("(([^\\\\]*\\\\){"n+1"}).*","\\1",1,$3)} 1' file
data,data,c:\path1\folder2\folder3\,data,data,data
data,data,c:\path1\folder2\folder3\,data,data,data
data,data,c:\path1\folder2\folder3\,data,data,data
data,data,c:\path1\folder2\folder3\,data,data,data
或使用任何 awk:
$ awk -v n=3 'BEGIN{FS=OFS=","} match($3,"(([^\\\\]*\\\\){"n+1"})"){$3=substr($3,1,RLENGTH)} 1' file
data,data,c:\path1\folder2\folder3\,data,data,data
data,data,c:\path1\folder2\folder3\,data,data,data
data,data,c:\path1\folder2\folder3\,data,data,data
data,data,c:\path1\folder2\folder3\,data,data,data
答案2
使用sed
,假设没有其他较早的字段包含由四个反斜杠分隔的字符串:
$ sed 's/\(\([^,\]\{1,\}[\]\)\{4\}\)[^,]*/\1/' file
data,data,c:\path1\folder2\folder3\,data,data,data
data,data,c:\path1\folder2\folder3\,data,data,data
data,data,c:\path1\folder2\folder3\,data,data,data
data,data,c:\path1\folder2\folder3\,data,data,data
或者,使用扩展的正则表达式,
$ sed -E 's/(([^,\]+[\]){4})[^,]*/\1/' file
data,data,c:\path1\folder2\folder3\,data,data,data
data,data,c:\path1\folder2\folder3\,data,data,data
data,data,c:\path1\folder2\folder3\,data,data,data
data,data,c:\path1\folder2\folder3\,data,data,data
这里使用的表达式sed
是替换,被替换的文本是匹配的任何内容(([^,\]+[\]){4})[^,]*
。此正则表达式匹配并捕获四个非空反斜杠分隔的字符串 ( ([^,\]+[\]){4}
)。这将被捕获以在替换字符串中重新使用,但直到并包括下一个逗号(无论尾随 匹配的内容[^,]*
)的所有内容都将被丢弃。
替换文本是\1
,它插入这四位反斜杠分隔的字符串。
显然,您也可以使用cut
and执行此操作,paste
但请注意以下命令管道读取文件三次,并删除第三个字段中路径名的最后一个反斜杠:
$ paste -d , <( cut -d , -f -2 file ) <( cut -d , -f 3 file | cut -d '\' -f -4 ) <( cut -d , -f 5- file )
data,data,c:\path1\folder2\folder3,data,data
data,data,c:\path1\folder2\folder3,data,data
data,data,c:\path1\folder2\folder3,data,data
data,data,c:\path1\folder2\folder3,data,data
您可以通过将前两个字段视为第三个字段中路径名的一部分来摆脱第一个字段cut
,但这仍然会读取文件两次:
$ paste -d , <( cut -d '\' -f -4 file ) <( cut -d , -f 5- file )
data,data,c:\path1\folder2\folder3,data,data
data,data,c:\path1\folder2\folder3,data,data
data,data,c:\path1\folder2\folder3,data,data
data,data,c:\path1\folder2\folder3,data,data
答案3
awk -F "\\" '{gsub(/\.*,/,",",$0);print $1"\\"$2"\\"$3"\\"$4$NF}' file.txt
data,data,c:\path1\folder2\folder3,data,data,data
data,data,c:\path1\folder2\folder3,data,data,data
data,data,c:\path1\folder2\folder3,data,data,data
data,data,c:\path1\folder2\folder3,data,data,data
Python
#!/usr/bin/python
import re
qw=re.compile(r'\.*')
k=open('file.txt','r')
for i in k:
respa=re.sub(qw,"",i.strip()).strip().split('\\')
print "{0}\\{1}\\{2}\\{3}{4}".format(respa[0],respa[1],respa[2],respa[3],respa[-1])
输出
data,data,c:\path1\folder2\folder3,data,data,data
data,data,c:\path1\folder2\folder3,data,data,data
data,data,c:\path1\folder2\folder3,data,data,data
data,data,c:\path1\folder2\folder3,data,data,data