标题: [文本处理] 求批处理把一个带分隔符的长字符串拆成一行行的 [打印本页]
作者: zhengwei007 时间: 2024-1-5 12:56 标题: 求批处理把一个带分隔符的长字符串拆成一行行的
本帖最后由 zhengwei007 于 2024-1-5 15:12 编辑
我有个csv文件,里面有很多类似的样式如下,我随意粘了3行,请大家帮忙看看,可以直接粘到csv里。- 1 adena 7 10 100 70 apprentice's_shoes 1 1 63.7931 cloth_shoes 1 1 12.069 leather_sandals 1 1 12.069 short_gloves 1 1 12.0689 10.9692 stem 1 1 75 suede 1 1 25 1.3062
- 3 adena 25 35 100 70 apprentice's_earing 1 1 30.9859 magic_ring 1 1 46.0094 necklace_of_magic 1 1 23.0047 15.1467 varnish 1 1 11.3636 coal 1 1 11.3636 charcoal 1 1 11.3636 rp_bow 1 1 9.0909 wooden_arrow 20 39 56.8183 6.0713
- 4 adena 34 48 100 70 short_leather_gloves 1 1 33.3333 cotton_shoes 1 1 33.3333 crude_leather_shoes 1 1 33.3334 2.4971 stem 1 1 75 suede 1 1 25 2.5262
复制代码
如果英文名称后面是4组数字,则将数字直接写在后面,然后另起一行。
如果英文名称后面是3组数字,则将将后面出现4组数字的最后一组,写到前面的最后一组给补齐即可。
所以根据上面的内容,我希望通过批处理操作后,自动调整成以下格式:- 1 adena 7 10 100 70
- 1 apprentice's_shoes 1 1 63.7931 10.9692
- 1 cloth_shoes 1 1 12.069 10.9692
- 1 leather_sandals 1 1 12.069 10.9692
- 1 short_gloves 1 1 12.0689 10.9692
- 1 stem 1 1 75 1.3062
- 1 suede 1 1 25 1.3062
- 3 adena 25 35 100 70
- 3 apprentice's_earing 1 1 30.9859 15.1467
- 3 magic_ring 1 1 46.0094 15.1467
- 3 necklace_of_magic 1 1 23.0047 15.1467
- 3 varnish 1 1 11.3636 6.0713
- 3 coal 1 1 11.3636 6.0713
- 3 charcoal 1 1 11.3636 6.0713
- 3 rp_bow 1 1 9.0909 6.0713
- 3 wooden_arrow 1 1 56.8183 6.0713
- 4 adena 34 48 100 70
- 4 short_leather_gloves 1 1 33.3333 2.4971
- 4 cotton_shoes 1 1 33.3333 2.4971
- 4 crude_leather_shoes 1 1 33.3334 2.4971
- 4 stem 1 1 75 2.5262
- 4 suede 1 1 25 2.5262
复制代码
这个是我把json格式的多余字符全删除了,这玩意原本是json。。。谢谢各位大佬。
作者: wanghan519 时间: 2024-1-5 15:12
本帖最后由 wanghan519 于 2024-1-5 15:49 编辑
py写的,不严谨,请小心测试,另外,json本身是啥样的,有可能简单一点- ret = []
- with open('a.csv', 'r') as f:
- for i in f:
- arr = i.strip().split('\t')
- a = arr[0]
- b = []
- for j in arr[1:]:
- try:
- float(j)
- b.append(j)
- except:
- if b:
- ret.append(b)
- if len(b) == 6:
- for k in ret:
- k.append(b[-1])
- b = [a, j]
- ret.append(b)
- for k in ret:
- k.append(b[-1])
- print('\n'.join(map(lambda x:'\t'.join(x[:6]), ret)))
复制代码
作者: zhengwei007 时间: 2024-1-5 15:22
py写的,不严谨,请小心测试,另外,json本身是啥样的,有可能简单一点
wanghan519 发表于 2024-1-5 15:12
不好意思,我没有PY的运行环境,也不太会用,最好是vbs。我把Json分享一下。
作者: zhengwei007 时间: 2024-1-5 15:27
- 1 additional_make_multi_list={{{{[adena];7;10;100}};70};{{{[apprentice's_shoes];1;1;63.7931};{[cloth_shoes];1;1;12.069};{[leather_sandals];1;1;12.069};{[short_gloves];1;1;12.0689}};10.9692};{{{[stem];1;1;75};{[suede];1;1;25}};1.3062}}
- 3 additional_make_multi_list={{{{[adena];25;35;100}};70};{{{[apprentice's_earing];1;1;30.9859};{[magic_ring];1;1;46.0094};{[necklace_of_magic];1;1;23.0047}};15.1467};{{{[varnish];1;1;11.3636};{[coal];1;1;11.3636};{[charcoal];1;1;11.3636};{[rp_bow];1;1;9.0909};{[wooden_arrow];20;39;56.8183}};6.0713}}
- 4 additional_make_multi_list={{{{[adena];34;48;100}};70};{{{[short_leather_gloves];1;1;33.3333};{[cotton_shoes];1;1;33.3333};{[crude_leather_shoes];1;1;33.3334}};2.4971};{{{[stem];1;1;75};{[suede];1;1;25}};2.5262}}
复制代码
这是他原来的JESON格式。
作者: wanghan519 时间: 2024-1-5 15:45
回复 4# zhengwei007
这也不是json啊。。。
没有可用的工具,能想到的就是用perl或者c#里正则的平衡组,好麻烦
还不如py写的,而且如果改用vb,vb里的数组又不能动态扩展,写起来更麻烦
作者: zhengwei007 时间: 2024-1-5 16:01
那我去试试你上面的PY
作者: zhengwei007 时间: 2024-1-5 16:22
本帖最后由 zhengwei007 于 2024-1-5 16:25 编辑
python我是一点不会,我进入环境了但不会运行~
我把文件发你,可以帮我导一下吗?
链接:https://pan.baidu.com/s/1jiRecvqIOPAw4dwRjOaGFw
提取码:eurj
--来自百度网盘超级会员V9的分享
作者: zhengwei007 时间: 2024-1-5 16:31
回复 zhengwei007
这也不是json啊。。。
没有可用的工具,能想到的就是用perl或者c#里正则的平 ...
wanghan519 发表于 2024-1-5 15:45
可以帮我加个写到一个新的文件中吗?我用网上的在线编译,可以使用。但内容过多,复制不完整。请帮我在代码最下面加一个可以生成一个新的文件,将所有结果全部写到b.csv里吧。
作者: wanghan519 时间: 2024-1-5 16:35
回复 8# zhengwei007 - ret = []
- with open('a.csv', 'r') as f:
- for i in f:
- arr = i.strip().split('\t')
- a = arr[0]
- b = []
- for j in arr[1:]:
- try:
- float(j)
- b.append(j)
- except:
- if b:
- ret.append(b)
- if len(b) == 6:
- for k in ret:
- k.append(b[-1])
- b = [a, j]
- ret.append(b)
- for k in ret:
- k.append(b[-1])
- with open('b.csv', 'w') as f:
- f.write('\n'.join(map(lambda x:'\t'.join(x[:6]), ret)))
复制代码
作者: idwma 时间: 2024-1-5 18:08
回复 4# zhengwei007
用4楼的例子,试一下系统自带的powershell
另存为bat文件运行- #@&cls&powershell "type '%~0'|out-string|iex"&pause&exit
- gc test.json|%{
- [regex]::Matches($_,'\{(?<k>{\[[^\]]+\][^\}]+\};?)+\};(?<v>[^\}]+)')|%{
- $v=$_.groups['v'].value
- $_.groups['k'].captures.value|%{$_ -replace '^\{\[([^\]]+)\];([^;]+);([^;]+);([^;]+)\};?',"`$1`t`$2`t`$3`t`$4`t$v"}
- }
- }
复制代码
作者: zhengwei007 时间: 2024-1-7 09:11
谢谢大家,已经解决了!
作者: aloha20200628 时间: 2024-1-7 12:47
用楼主在4楼提供的样本(存为:样本3行.txt)练了一把纯P脑力操,代码如下存为test.bat
先用字符串替换函数把源文收拾利索,再丢给 for/f 分割器逐项扫描.. 幸亏有变量名字典作为遍历回查存储器,使得代码轻量化...
再用7楼提供的样本文件(下载保存为:样本462行.txt)运行结果输出4370行一楼所求格式化数据,行内分割符为制表符
test.bat "样本3行.txt">"样本3行.new"
或
test.bat "样本462行.txt">"样本462行.new"- @echo off
- for /f "tokens=1* delims= " %%1 in (%1) do (
- setlocal enabledelayedexpansion
- set "dn=0" &set "nq=%%1" &set "s=%%2;z" &set "s=!s:*{=!"
- for %%c in ( [,],{,} ) do (set "s=!s:%%c=!")
- for %%a in (!s!) do (
- set "v=%%a" &set "v1=!v:~,1!"
- if "!v1!" geq "0" if "!v1!" leq "9" (
- for %%k in (!n!) do (set "_%%k=!_%%k! !v!")
- set "lastD=!v!" &set/a "dn+=1"
- ) else (
- if !dn! equ 3 (set "nmax=!nmax! !n!") else if !dn! equ 4 (
- if defined nmax for %%k in (!nmax!) do (echo,!_%%k! !lastD!)
- for %%k in (!n!) do (echo,!_%%k!)
- set "n=0" &set "nmax="
- )
- set/a "n+=1, dn=0" & set "_!n!=!nq! !v!"
- )
- )
- endlocal
- )
- exit/b
复制代码
作者: qixiaobin0715 时间: 2024-1-11 14:28
本帖最后由 qixiaobin0715 于 2024-1-12 11:11 编辑
考虑不是太成熟,代码应当还能简化,只是提供一种思路:- @echo off
- setlocal enabledelayedexpansion
- (for /f "tokens=1*" %%a in (a.csv) do (
- setlocal enabledelayedexpansion
- set FirstCol=%%a
- for %%j in (%%b) do (
- for /f "delims=0123456789." %%k in ("#%%j") do (
- if not "%%k"=="#" (
- if !x! equ 3 (
- set /a y+=1
- set _!y!=!str!
- ) else if !x! equ 4 (
- if defined _!y! (
- for /l %%l in (1,1,!y!) do (
- if defined FourthCol (
- echo,%%a !_%%l! !FourthCol!
- ) else (
- echo,%%a !_%%l!
- )
- set _%%l=
- )
- set FourthCol=
- set y=0
- )
- echo,%%a !str!
- )
- set str=%%j
- set x=0
- ) else (
- set str=!str! %%j
- set /a x+=1
- if !x! equ 4 set FourthCol=%%j
- )
- )
- )
- if defined _!y! (
- for /l %%l in (1,1,!y!) do (
- if defined FourthCol (
- echo,!FirstCol! !_%%l! !FourthCol!
- ) else (
- echo,!FirstCol! !_%%l!
- )
- )
- )
- echo,!FirstCol! !str!
- endlocal
- ))>out.csv
- pause
复制代码
作者: qixiaobin0715 时间: 2024-1-12 11:08
本帖最后由 qixiaobin0715 于 2024-1-12 11:20 编辑
主要是练练手。
将楼上代码修改如下:- @echo off
- setlocal enabledelayedexpansion
- (for /f "tokens=1*" %%a in (a.csv) do (
- setlocal enabledelayedexpansion
- for %%j in (%%b,x) do (
- for /f "delims=0123456789." %%k in ("#%%j") do (
- if not "%%k"=="#" (
- if !x! equ 3 (
- set /a y+=1
- set _!y!=!str!
- ) else if !x! equ 4 (
- if defined _!y! (
- for /l %%l in (1,1,!y!) do (
- if defined FourthCol (
- echo,%%a !_%%l! !FourthCol!
- ) else (
- echo,%%a !_%%l!
- )
- set _%%l=
- )
- set FourthCol=
- set y=0
- )
- echo,%%a !str!
- )
- set str=%%j
- set x=0
- ) else (
- set str=!str! %%j
- set /a x+=1
- if !x! equ 4 set FourthCol=%%j
- )
- )
- )
- endlocal
- ))>out.csv
- pause
复制代码
作者: qixiaobin0715 时间: 2024-1-12 15:11
本帖最后由 qixiaobin0715 于 2024-1-12 16:32 编辑
13、14楼提供代码好像不行,刚发现楼主提供的csv文件在599行中,英文名称含有空格,分割时会出现问题。以上代码作废。
使用不带参数的for循环,按水平制表符分割字符串时不能存在干扰字符,即要分割的字符串中不能存在空格、逗号、分号、等号等这类字符,这种情况应当也能解决,不过可能要在前面多几行代码处理一下字符串即可。
作者: qixiaobin0715 时间: 2024-1-16 10:26
修改14楼的代码,以便解决15楼的问题:- @echo off
- setlocal enabledelayedexpansion
- (for /f "tokens=1*" %%a in (a.csv) do (
- setlocal enabledelayedexpansion
- set Line="%%b"
- set Line=!Line: =" "!
- set Line=!Line:""=!
- for %%j in (!line!,x) do (
- for /f "delims=0123456789." %%k in ("#%%~j") do (
- if not "%%k"=="#" (
- if !x! equ 3 (
- set /a y+=1
- set _!y!=!str!
- ) else if !x! equ 4 (
- if defined _!y! (
- for /l %%l in (1,1,!y!) do (
- if defined FourthCol (
- echo,%%a !_%%l! !FourthCol!
- ) else (
- echo,%%a !_%%l!
- )
- set _%%l=
- )
- set FourthCol=
- set y=0
- )
- echo,%%a !str!
- )
- set str=%%~j
- set x=0
- ) else (
- set str=!str! %%~j
- set /a x+=1
- if !x! equ 4 set FourthCol=%%~j
- )
- )
- )
- endlocal
- ))>out.csv
- pause
复制代码
这种问题对于锻炼逻辑思维很有好处。顺便练习一下if及set命令的用法。
作者: hfxiang 时间: 2024-1-16 13:11
回复 1# zhengwei007
此类在俺看来属于数据格式化一类的问题,建议用第3方工具gawk(http://bcn.bathome.net/tool/4.1.0/gawk.exe)处置,其在命令行下实现指令如下:- gawk "{n=patsplit($0,a,/[a-zA-Z][^\t]+(\t[0-9.]+){3,4}/);for(i=n;i>0;i--)if(a[i]~/[a-zA-Z][^\t]+(\t[0-9.]+){4}/){a4=gensub(/^.+\t([^\t]+)$/,\"\\1\",\"g\",a[i])}else{a[i]=a[i] \"\t\" a4};for(i=1;i<=n;i++)print $1\"\t\"a[i]}" a.csv>b.txt
复制代码
作者: newswan 时间: 2024-1-16 14:33
#10 的powershell 很合适啊
欢迎光临 批处理之家 (http://bbs.bathome.net/) |
Powered by Discuz! 7.2 |