批处理之家's Archiver

batman 发表于 2009-8-15 01:18

【练习-037】批处理去除文本行前后的空格

[color=black]  因为论坛练习题系列中确实缺少37题(这是本人的过失),所以就
以本题来做为37题吧。有文本a.txt如下:[code] amd cx qu      
    k of woo is qmom                 
      jm ko    ppp     oe    mie    tnnn           
  sis              jb  [/code]  要求通过批处理去除文本行的前后空格(空格数是随机和末知的
,且都为半角空格),输出如下(行的前后请加上引号):[code]"amd cx qu"
"k of woo is qmom"
"jm ko    ppp     oe    mie    tnnn"
"sis              jb"[/code]  本题满分10分,原则上以思路为重,视情况加分。
       参考答案如下:
[code]@echo off
for /f "delims=" %%a in (a.txt) do set "a="&call :lp "$%%a$"
pause>nul&goto :eof
:lp
for /f "tokens=1* delims= " %%a in ("%a%%~1") do set "str=%%b"&set "var="
for %%a in (%str: = # %) do call,set "var=%%a%%var%%"
if "%~1" neq "" (set "a=%var:#= %"&call :lp) else echo "%var:#= %"[/code][/color]

[[i] 本帖最后由 batman 于 2009-8-15 18:44 编辑 [/i]]

netbenton 发表于 2009-8-15 08:13

[color=black]以前在cn - dos见过这种方法:
[code]@echo off
set "abc=                    33 ff cc                  "
for /f "tokens=*" %%a in ("%abc%") do echo;"%%~nxa"[/code][/color]

[[i] 本帖最后由 batman 于 2009-8-15 18:45 编辑 [/i]]

batman 发表于 2009-8-15 11:48

回复 2楼 的帖子

&&震撼!学习了。想不到变量扩展能强到如此地步,
但就是不明白其中的处理机制,希望有高人能明示
一二。
   另请大家不要局限于现有的解决方案,把思路充
分打开,“八仙过海各显神通”,这也是本人不断出
题的初衷了。

kevinpeng 发表于 2009-8-15 12:52

回复 2楼 的帖子

哪位兄台能否解释一下这样为什么也可以,%%~nxa不是指的文件名及扩展名么?

keen 发表于 2009-8-15 13:46

用了5个FOR:[code]@echo off&setlocal enabledelayedexpansion
for /f "tokens=*" %%i in (a.txt) do (
    set str=%%i
    for %%a in (%%i) do set str1=%%a
    for %%h in (!str1!) do (
        for %%m in (!str1!#) do set hh=!str:%%h=%%m!
        for /f "delims=#" %%x in ("!hh!") do echo "%%x"
    )
)
pause[/code]

keen 发表于 2009-8-15 14:48

只能去掉末尾100个空格,要是大于100个空格,必须改动for /l中的数字,这也是此代码的不合理之处:[code]@echo off&setlocal enabledelayedexpansion
for /f "tokens=*" %%i in (a.txt) do (
    set str=%%i
    call :lp
)
pause&exit/b

:lp
for /l %%a in (-1 -1 -100) do (
        set "str1=!str:~%%a,1!"
        if not "!str1!"==" " (
           set n=%%a&set /a n+=1
           for %%i in (!n!) do set "str1=!str:~0,%%i!"
           echo "!str1!"&goto :eof
        )
)[/code]

基拉freedom 发表于 2009-8-15 15:49


测试了下 2L的
发现只需要用~n就好了(用x也许有特殊的情况吧)................................[code]@echo off
for /f "tokens=*" %%a in (a.txt) do (
echo "%%~na"
)
pause[/code]%~nI        - 仅将 %I 扩充到一个文件名
自己想了想
原因也许是:
对于文件名(这里指的是文件夹) win规定了开头和末尾都不允许有空格.......于是有的就自动去掉了
..
用md也无法建立前头和末尾有空格的文件夹

基拉freedom 发表于 2009-8-15 16:13

对于以上 我的想法
想出了一种dir的方法 建立文件夹 然后删除
这个方法最要命的就是 一定要放在一个没有文件夹的目录下 否则就................[code]@echo off
for /f "tokens=*" %%a in (1.txt) do (
md "%%a"
for /f "tokens=*" %%t in ('dir /b *.') do echo "%%t"
rd "%%a"
)
pause[/code]这道题目等多点人解答 我再放到chm里去^_^

基拉freedom 发表于 2009-8-15 16:17

以上的改进是建立双层的文件夹 呼呼
把思路提出来 以后再改了 做完才想到的
要下网了 8

kevinpeng 发表于 2009-8-15 17:05

其实可以创建一个无字节的文件名,方法就是用截取字符串的办法可以把原有的文件名换没了!如:
%str:filename=%

netbenton 发表于 2009-8-15 17:52

考虑了特殊情况:即存在":" "<>" "\" "."
[code]
@echo off
set "abc=   33 ff c:\ab\exe.ffg  00 0 0-00-><   "
set "abc=%abc:0=-0-%"
set "abc=%abc::=a0%"
set "abc=%abc:\=b0%"
for /f "tokens=*" %%a in ("%abc%") do set "abc=%%~nxa"
set "abc=%abc:b0=\%"
set "abc=%abc:a0=:%"
set "abc=%abc:-0-=0%"
echo;"%abc%"
[/code]

terse 发表于 2009-8-15 18:32

[code]@echo off
set "str=   33 ff c:\ab\exe.ffg  echo;00 0 0-00->55.txt<   "
for /f "tokens=*" %%i in ("%str%") do set "str=%%i"
:lp
if "%str:~-1%"==" " set "str=%str:~0,-1%"&goto lp
echo "%str%"
pause[/code]

batman 发表于 2009-8-15 18:49

回复 12楼 的帖子

逐字法效率一直是问题,这点是无法避免的。。。

terse 发表于 2009-8-15 20:30

这样效率提高点吧[code]@echo off
set "str=   33 ff c:\ab\exe.ffg  echo;00 0 0-00->55.txt<   "
for /f "tokens=*" %%i in ("%str%") do (
   for %%j in ("c:\%%i") do set "str=%%~pnxj"
)
echo "%str:~1%"
pause[/code]

batman 发表于 2009-8-15 20:39

回复 5楼 的帖子

代码是否可以做如下修改(去掉两个for),但文本中如存在#字符这个代码就挂掉了:
[code]@echo off&setlocal enabledelayedexpansion
for /f "tokens=*" %%i in (a.txt) do (
    set str=%%i
    for %%a in (%%i) do set str1=%%a
    call, set hh=%%str:!str1!=!str1!#%%
    for /f "delims=#" %%x in ("!hh!") do echo "%%x"
)
pause[/code]

[[i] 本帖最后由 batman 于 2009-8-15 20:42 编辑 [/i]]

keen 发表于 2009-8-15 20:51

回复 15楼 的帖子

之所以不用call,是以为随风在一篇讨论效率的帖子中说过,如果出现这种方式(call, set hh=%%str:!str1!=!str1!#%%),还是用for的好。
具体参看:
[url]http://bbs.bathome.net/viewthread.php?tid=4831&highlight=%2B%CB%E6%B7%E7[/url]

wxcute 发表于 2009-8-15 21:04

今天回到家了,我也来凑个数^_^

[code]@echo off
for /f "tokens=* delims= " %%s in (a.txt) do call :str %%s
pause
:str
echo "%*"[/code]

batman 发表于 2009-8-15 21:07

&&修改下我顶楼的代码,顶楼原来是想通用一系列的技巧来简化代码,
结果是付出了效率上的代价,现提高代码运行效率如下:[code]@echo off&setlocal enabledelayedexpansion
for /f "delims=" %%a in (a.txt) do (
    for /f "tokens=*" %%a in ("%%a") do set "str=%%a"&set "str=!str: = # !"&set "var="
    for %%a in (!str!) do set "var=%%a!var!"
    set "var=!var:#= !"
    for /f "tokens=*" %%a in ("!var!") do set "str=%%a"&set "str=!str: = # !"&set "var="
    for %%a in (!str!) do set "var=%%a!var!"
    echo "!var:#= !"
)
pause>nul[/code]

shqf 发表于 2009-8-15 21:47

综合一下,还可如下
@echo off
for /f "tokens=* delims= " %%s in (a.txt) do echo "%%~nxs"
pause

Lumiere 发表于 2009-8-16 00:32

[code]@echo off&setlocal enabledelayedexpansion
for /f "tokens=*" %%a in (a.txt) do set "var=%%a"&call :loop&echo "!var!">>b.txt
goto :eof
:loop
set "check=!var:~-1!"&if "!check!"==" " set "var=!var:~0,-1!"&goto loop[/code]

[[i] 本帖最后由 Lumiere 于 2009-8-16 00:36 编辑 [/i]]

Lumiere 发表于 2009-8-16 20:38

[quote]原帖由 [i]wxcute[/i] 于 2009-8-15 21:04 发表 [url=http://bbs.bathome.net/redirect.php?goto=findpost&pid=36010&ptid=5584][img]http://bbs.bathome.net/images/common/back.gif[/img][/url]
@echo off
for /f "tokens=* delims= " %%s in (a.txt) do call :str %%s
pause
:str
echo "%*" [/quote]
你的delims= 似乎是多余的吧?tokens=*不是不会分节字符串的么?
还有啊,%*我现在还不是太明白,能给讲解一下么

terse 发表于 2009-8-16 21:12

不考虑特殊字符的话 call出来 echo %* 效率可以
利用%%~nxi扩展的话 路径的处理上也有问题
我再用替换法  发现效率比不上echo %*
文本中有一个引号的话也出错 两引号之间没空格可以处理[code]@echo off&setlocal enabledelayedexpansion
for /f "tokens=*" %%i in (a.txt) do (
    set var=%%i&set str=&set "k= "
    set "var=!var: =" "!"
    for %%a in ("!var!") do if %%a neq "" (
        set "str=!str!!k!%%~a"&set "k= "
      ) else set "k= !k!"
        echo "!str:~1!"
   )
pause[/code]

leap 发表于 2010-10-28 14:22

回复 7楼 的帖子

[code]@echo on&setlocal enabledelayedexpansion
for /f "tokens=*" %%i in (a.txt) do (
        md "d:\2\%%i")
for /f "delims=" %%i in ('dir /b "d:\2\"') do echo "%%i">>2.txt
rd/s/q d:\2\
pause[/code]

Hello123World 发表于 2011-7-20 19:34

参照2楼的算法,但不知道原理。[code]@echo off
For /f "Tokens=*" %%i in (a.txt) do (For /f "tokens=*" %%a in ("%%i") do Echo "%%~nxa")
pause[/code]

Seder 发表于 2011-9-3 13:16

有分加那么好??[code]sed -e "s/^[ ]*//;s/[ ]*$//;s/\(.*\)/\"\1\"/" test.txt[/code]

zaixinxiangnian 发表于 2011-9-3 20:39

[b]回复 [url=http://www.bathome.net/redirect.php?goto=findpost&pid=35962&ptid=5584]5#[/url] [i]keen[/i] [/b]


    你这个还好理解些,但到这里就想不通了。  为什么有个#号?如果有时间每句给解释下就有富了

for %%h in (!str1!) do (

        for %%m in (!str1!#) do set hh=!str:%%h=%%m!

        for /f "delims=#" %%x in ("!hh!") do echo "%%x"

civen 发表于 2011-9-26 19:44

[quote]&&修改下我顶楼的代码,顶楼原来是想通用一系列的技巧来简化代码,
结果是付出了效率上的代价,现提高代码 ...
[size=2][color=#999999]batman 发表于 2009-8-15 21:07[/color] [url=http://bbs.bathome.net/redirect.php?goto=findpost&pid=36011&ptid=5584][img]http://bbs.bathome.net/images/common/back.gif[/img][/url][/size][/quote]


有点不完美. 空行带空格的还得输出一个空格

yashuer 发表于 2012-7-5 12:29

[code]发个sed的
#!/bin/bash
# Fri Jun 22 15:43:42 CST 2012
# Sun Jul  1 19:52:32 CST 2012
# The code is listed as follows
echo >uu.txt
sed 's/^\s*\(.*[a-z]\)\s*$/\1/g' temp > uu.txt
exit[/code]

踏沙行 发表于 2018-11-6 09:12

[i=s] 本帖最后由 踏沙行 于 2018-11-6 09:17 编辑 [/i]

[b]回复 [url=http://www.bathome.net/redirect.php?goto=findpost&pid=35944&ptid=5584]2#[/url] [i]netbenton[/i] [/b]
旧贴重提,不知道论坛是否有禁止性规定?
使用扩展变量%~nx,固定速度快,但是假如,文本中包含有路径符号 \ 的话,就悲剧了。
比如:1.txt内容如下:
   A11 !b11 H\c11 ^E
      A13 B13\22\123 #C13 E

踏沙行 发表于 2018-11-6 09:14

[i=s] 本帖最后由 踏沙行 于 2018-11-6 09:19 编辑 [/i]

[quote]
[size=2][color=#999999]wxcute 发表于 2009-8-15 21:04[/color] [url=http://www.bathome.net/redirect.php?goto=findpost&pid=36010&ptid=5584][img]http://www.bathome.net/images/common/back.gif[/img][/url][/size][/quote]
原贴代码:[code]@echo off
for /f "tokens=* delims= " %%s in (a.txt) do call :str %%s
pause
:str
echo "%*"[/code]这个方法也很好,但是有个困惑:怎么取得返回值?
如果我想把每行首尾的空格去掉后,再将结果返回给主程序中的某个变量,该怎么实现?

页: [1] 2

Powered by Discuz! Archiver 7.2  © 2001-2009 Comsenz Inc.