Board logo

标题: 如何用批实现TXT文本的某两行互换? [打印本页]

作者: lotus516     时间: 2006-11-6 03:07    标题: 如何用批实现TXT文本的某两行互换?

我有一个文本,里面内容如下:
张三
李四
王二麻子
小白
小黑
小强
......    rem:中间为N行
小二
赵大
QQ
DOS
WIN98
WINXP
现在我想实现把WINXP和张三互换成如下文本:(即文本第一行和最后一行互换)
WINXP
李四
王二麻子
小白
小黑
小强
......        rem:中间为N行
小二
赵大
QQ
DOS
WIN98
张三
作者: redtek     时间: 2006-11-6 05:48
只按楼主给出的原始模型处理,
以下代码只考虑到楼主上面非真实模型上的要求,
不考虑楼主没有给出的特殊情况或特殊符号等问题~:)
@echo %dbg% off
setlocal enabledelayedexpansion
if [%4]==[] goto :error
if exist %4 del /q %4

for /F "delims=" %%. in (%1) do (set /a line+=1 && set "num!line!=%%.")
(set swapTemp=!num%3!) && (set num%3=!num%2!) && (set num%2=!swapTemp!)
for /L %%i in (1,1,!line!) do (echo !num%%i!>>%4)
start %4
goto :eof

:error
        echo.
        echo 使用说明:%0.Bat  要处理的文件名  交换行数   被交换行数  交换后文件名
        echo.
        echo 例(A):%0.Bat swap.dat  5 10 a.txt
        echo        处理swap.dat文件,第5行与第10行数据交换,生成新文件:a.txt
        echo.
使用说明: 如果未加参数则提示使用说明信息。
使用说明: Swap.BAT  要处理的文件名  交换行数   被交换行数  交换后文件名

       
   例: Swap.BAT    swap.dat    5    10    a.txt
  表示: 处理 swap.dat 文件,第5行与第10行数据交换,生成新文件:a.txt
      Swap.BAT 文件为这个处理交换数据的批处理文件名,楼主可以任意起。
原理: 大老婆和二老婆想互相交换她们手中的礼物,
    于是大老婆先把礼物暂存在我这里,手腾空了后把二老婆的礼物拿了过去。
    二老婆的礼物交给了大老婆以后,手腾空了。这时我再把大老婆暂存在我手中的礼物交给二老婆。
    于是她们双方都互换了礼物~:)


[备注:] 指定生成的新文件如果是已存在的文件,它将自动无提示删除。

[ Last edited by redtek on 2006-11-6 at 05:50 AM ]
作者: namejm     时间: 2006-11-6 05:55
  假设你要处理的test.txt文本中没有CMD下的敏感字符(如<、>、|等),首行不为空,并且没有内容重复的行,那么,用下面的代码基本能满足你的需求:
@echo off
:: 思路:
::     提取第一行和最后一行内容(若最后一行是空行,则提取到的是非空的最后一行内容),
:: 然后在新文本的首行写入提取到的最后一行,用 findstr 语句过滤掉原文本的第一行和最后一行,在最后一行
:: 之后添加提取到的第一行。
:: 因为 findstr 处理最后一行有条件限制,所以先在最后一行之后生成一个空行,以保证提取的准确性
copy test.txt test.bak>nul
echo.>>test.txt
set num=0
setlocal enabledelayedexpansion
for /f "delims=" %%i in (test.txt) do (
    set str=%%i
    set /a num+=1
    if !num! equ 1 set var=%%i
)
>test_.txt echo.%str%
findstr /b /e /v /c:"%str%" /c:"%var%" test.txt>>test_.txt
>>test_.txt echo.%var%
move test.bak test.txt
start test_.txt
[ Last edited by namejm on 2006-11-6 at 02:03 PM ]
作者: redtek     时间: 2006-11-6 05:56
本来应该为方便楼主应用,
例如:想让第3行与倒数第3行交换,则

   Swap.BAT    swap.dat    3   -3    a.txt
 或 Swap.BAT    swap.dat    3   a.txt

如果能这样会更方便楼主,实在是力不从心,谅~~
作者: namejm     时间: 2006-11-6 07:06
  在3F的基础上得到如下代码,可以处理内容有重复的行。原理和3F近似,只是过滤的不再是行内容,而是过滤行号:
@echo off
:: 注意:因为 findstr /n 统计行数的时候,会忽略最后一个空行
:: 所以,若在最后有空行的话,请保证空行的个数大于1
findstr /n .* test.txt>tmp1.txt
for /f "tokens=1* delims=:" %%i in (tmp1.txt) do (
    if %%i equ 1 set str=%%j
    set line=%%i&set var=%%j
)
>tmp2.txt echo %line%:%var%
findstr /b /v /c:"1:" /c:"%line%:" tmp1.txt>>tmp2.txt
echo 1:%str%>>tmp2.txt
echo.>>tmp2.txt
cd.>result.txt
for /f "tokens=1* delims=:" %%i in (tmp2.txt) do >>result.txt echo.%%j
del /q tmp1.txt tmp2.txt
start result.txt

作者: vkill     时间: 2006-11-6 07:31
sed -n "$p" >temp.txt
sed "1{d;p}" test.txt |sed "${d;p}" >>temp.txt
sed -n "1p" >>temp.txt

未测试,原理上可行
作者: lotus516     时间: 2006-11-6 11:59
谢谢,不过namejm,3楼的命令不成功!!!
作者: namejm     时间: 2006-11-6 12:33
  3F的代码有诸多限制,如果我说漏了某些情况,能否把你的txt内容贴一部分出来?
作者: lotus516     时间: 2006-11-7 01:48
好,详细见附件
附件 1: 1.txt (2006-11-7 01:48, 2.39 K, 下载附件所需积分 1点 ,下载次数: 19)

作者: namejm     时间: 2006-11-7 01:59
  不好意思,发帖子的时候,copy了修改前的代码,而没有帖出修正后的内容,导致3F的代码漏掉了写入首行和尾行的语句,现已修正,请再次测试。
作者: vkill     时间: 2006-11-7 09:07
test.bat
@echo off
::%1为life,调换%2和%3
::比如说在test.txt中调换1行和9行,使用方法test.bat test.txt,1,9
::暂时不能换3,-3之类的,不过可以sed -n "$=" %1 来看总共有多少行~再set/a计算实际的+行数

if *%1==* (echo 未指定文件&pause>nul&goto :eof)
if *%2==* (set s=1) else (set s=%2)
if *%3==* (set e=$) else (set e=%3)
if not "%e%"=="$" if %e% lss %s% (set "s=%3"&set "e=%2")

for /f "tokens=*" %%? in ('sed -n "%e%p" %1') do (
                       sed -e "%s%h" -e "%e%x" %1|sed "%s% c\%%?" |more>temp.txt
                                                  )
pause
exit



测试test.txt
`-=[]\;',./~!@#o^&*()_+{}|:"<>?
ab
AB
12 34
一二三四五六七八九○
!·¥……—()——:“?》《
http ://abc.abc.abc/

[ Last edited by vkill on 2006-11-7 at 09:55 AM ]
作者: namejm     时间: 2006-11-7 09:23
  网吧里的系统一般都是被阉割过的,有安全问题的命令可能都被废了。
作者: vkill     时间: 2006-11-7 09:31


  Quote:
Originally posted by namejm at 2006-11-7 09:23:
  网吧里的系统一般都是被阉割过的,有安全问题的命令可能都被废了。

namejm兄测试下,原理是先把9替换为1,再把1复制为原文件9的内容~

11 F代码更新

[ Last edited by vkill on 2006-11-7 at 09:58 AM ]
作者: namejm     时间: 2006-11-7 10:24
  居然没有保存 sed 程序,我知道无奈何兄最近刚发过,但一时也搜索不到它的下载,汗~~,能给个下载的地址吗?
作者: 无奈何     时间: 2006-11-7 11:09
我也补个 sed 的,文件不要过于巨大。
sed -re :a -e "N;$!ba;s/([^\n]*)\n(.*)\n(.*)/\3\n\2\n\1/"
sed 下载:http://www.student.northpark.edu/pemente/sed/gsed407x.zip
作者: vkill     时间: 2006-11-9 02:11


  Quote:
Originally posted by 无奈何 at 2006-11-7 11:09:
我也补个 sed 的,文件不要过于巨大。
sed -re :a -e "N;$!ba;s/([^\n]*)\n(.*)\n(.*)/\3\n\2\n\1/"
sed 下载:http://www.student.northpark.edu/pemente/s ...

斑竹的sed用法看不懂还,我复制回去查查资料先
作者: 3742668     时间: 2006-11-9 10:50

@echo off
setlocal ENABLEDELAYEDEXPANSION
    set file=a.txt
    for /f "delims=: tokens=1,*" %%i in ('findstr /n .* "%file%"') do set "%%i=%%j" & set num=%%i
    set "str=!%~1!"
    set "%~1=!%~2!"
    set "%~2=%str%"
    for /l %%i in (1,1,%num%) do if defined %%i (echo.!%%i!) else echo.
pause
利用上面的原理,实现3,-3并不难。
刚才写上面的东西的时候朋友喊我去帮忙做了系统的, 不知道有无bug,反正原理就那些了。
作者: redtek     时间: 2006-11-9 11:47
版主让行号直接模拟数组变量的方法真巧妙~:)
能看到这么好玩的内容简直太过瘾了~:)
作者: vkill     时间: 2006-11-11 07:55
我在想 3742668 斑竹的代码在行中遇到 | 会不会执行~我试了好象不可以
作者: 3742668     时间: 2006-11-13 06:40


  Quote:
我在想 3742668 斑竹的代码在行中遇到 | 会不会执行~我试了好象不可以

有无加参数?
我这里测试正常。
作者: amao     时间: 2007-2-2 16:33
无奈何斑竹的代码在解决小文本时简洁利索;
vkill的代码在文本最后一行没有回车(换行)符时,会出错;
我也发一下我的代码吧,基于sed的

@echo off
sed -n "$!d;G;P" a.txt> temp.txt
sed "1d;$d" a.txt>> temp.txt
sed q a.txt>> temp.txt
type temp.txt
pause

它不管文本最后一行有无回车(换行)符都起作用

[ Last edited by amao on 2007-2-2 at 05:18 PM ]
作者: anqing     时间: 2007-2-3 00:02
p能写成这样的要求,真不容易
作者: vkill     时间: 2007-2-3 05:06


  Quote:
Originally posted by amao at 2007-2-2 16:33:
无奈何斑竹的代码在解决小文本时简洁利索;
vkill的代码在文本最后一行没有回车(换行)符时,会出错;
我也发一下我的代码吧,基于sed的

@ech ...

兄也喜欢sed ?呵呵
作者: amao     时间: 2007-2-3 11:06


  Quote:
Originally posted by vkill at 2007-2-3 05:06:

兄也喜欢sed ?呵呵

正在努力学习中
作者: ArchieYao     时间: 2007-11-29 23:22
顶上来问一下
如楼主给出的文本内容,如果我要互换含"张三" 和"小二"的行,怎么处理
想听听用sed的处理办法:)