请帮我创建一个脚本来执行如下所述的任务。
我有2个文件,A.txt
和B.txt
。 A.txt
的内容如下所示
ITEM name TICKY title nice coffe drink type DRINK ITEM name APPLE title sweet tasty apple type FRUIT ITEM name JUICE title nice tasty drink type DRINK ITEM name ORANG title niice nice orange type FRUIT ITEM name CHERY title nutritious rich fruit type FRUIT
现在,我需要在A.txt
中搜索单词"FRUIT"
,然后将"FRUIT"
顶部的第二行复制到名为list.txt
的新文件中。
但我只需要水果的名称,list.txt
应该如下所示。
APPLE ORANG CHERY
这是我的编码(powershell)来做到这一点......
$source = "C:\temp\A.txt"
$destination = "C:\temp\list.txt"
$hits = select-string -Path $source -SimpleMatch "type FRUIT" -CaseSensitive
$filecontents = get-content $source
foreach($hit in $hits)
{
$filecontents[$hit.linenumber-3]| out-file -append $destination
"" |out-file -append $destination
}
这将按照以下
提取第二个顶行name APPLE name ORANG name CHERY
以下编码(.bat)将删除单词"name"
@echo off
setlocal enabledelayedexpansion
del list2.txt
for /f "tokens=*" %%a in (C:\temp\list.txt) do (
set line=%%a
set chars=!line:~-13,13!
echo !chars! >> list2.txt
)
作为第二阶段,我现在需要在我的list.txt
中的APPLE
文件(ORANG
,CHERY
,B.txt
)中搜索单词,如下所示。
ITEM p_date 10/03/15 pt_time 11:29:40:00 title nice coffe drink name TICKY stock yes end ITEM p_date 10/03/15 pt_time 11:29:40:00 title sweet tasty apple name APPLE stock yes end ITEM p_date 10/03/15 pt_time 11:29:40:00 title nice tasty drink name JUICE stock yes end ITEM p_date 10/03/15 pt_time 11:29:40:00 title niice nice orange name ORANG stock yes end ITEM p_date 10/03/15 pt_time 11:29:40:00 title nutritious rich fruit name CHERY stock yes end
我必须在list.txt
中搜索来自B.txt
的字词,并提取3个顶行并将其相应地写在名为done.txt
的新文件中。下面是我的编码(powershell)。
$source = "C:\temp\B.txt"
$destination = "C:\temp\done.txt"
$patterns = Get-Content c:\temp\list2.txt | Where-Object{$_}
$results = Select-String c:\temp\done.txt -Pattern $patterns -SimpleMatch
$results.Line | ForEach-Object{"$_`r`n"} | Set-Content c:\temp\done.txt
foreach($hit in $hits)
{
$filecontents[$hit.linenumber-4]| out-file -append $destination
$filecontents[$hit.linenumber-3]| out-file -append $destination
$filecontents[$hit.linenumber-2]| out-file -append $destination
$filecontents[$hit.linenumber-1]| out-file -append $destination
"" |out-file -append $destination
}
我设法为此开发编码。但我需要3个脚本文件(2个PowerShell和1个批处理)才能完成此操作。
请帮助我在一个脚本中完成此任务。如果它在.vbs或.bat中最好。
答案 0 :(得分:0)
你走了。我必须做一些创造性的工作才能使这一切融合在一起。例如,我首先在B.txt中搜索与.txt中匹配的水果名称而不是两个脚本,然后构建一个自定义对象数组,以便于搜索,如下所示:
#Mark the word ITEM as the start of each record
$BHits = Select-String -Path $BSource -SimpleMatch "ITEM" -CaseSensitive -Context 5
#Make an empty array to hold our PowerShell Objects
$fruitMatches = @()
$output = @()
#Make $FruitMatches contain our purchase records
ForEach ($bhit in $BHits){
$fruitMatches += [pscustomobject]@{Fruit=$BHit.Context.PostContext[3].Replace("name ",'');
Date=$BHit.Context.PostContext[0].Replace('p_date ','');
Time=$BHit.Context.PostContext[1].Replace('pt_time ','')}
}
为什么我这么做呢?好吧,首先,您想要从Select-String输出中删除Name这个词。事实证明,你可以通过使用-Context来告诉PowerShell刮掉一定数量的行以及匹配,并且选择你想要的特定行就像索引这样对象一样容易:
#In one line, find the word type Fruit, and remove the word 'name'
($hit.Context.PreContext[0].Replace('name','').Trim())
>Cherry
现在知道,当你看到$hit.Context...
长的字符串时,它会解析为水果的名字。好吧,我们打扰制作自定义对象的原因是,我可以轻松搜索匹配的对象,如下所示:
ForEach ($hit in $hits){
$fruitMatches | ? Fruit -eq ($hit.Context.PreContext[0].Replace('name','').Trim())
}
这会给我们以下输出:
Fruit Date Time
----- ---- ----
APPLE 10/03/15 11:29:40:00
ORANG 10/03/15 11:29:40:00
CHERY 10/03/15 11:29:40:00
从这一点来说,我只是创建一些空数组来保存结果,并通过使用重定向字符>
转储输出来结束整个事情。
这用一个脚本回答你的整个前提。如果您对此如何运作有任何疑问,请与我们联系。
已完成答案
$source = "T:\A.txt"
$BSource = "t:\b.txt"
$destination = "T:\done.txt"
#Mark the word ITEM as the start of each record
$BHits = Select-String -Path $BSource -SimpleMatch "ITEM" -CaseSensitive -Context 5
#Make an empty array to hold our PowerShell Objects
$fruitMatches = @()
$output = @()
#Make $FruitMatches contain our purchase records
ForEach ($bhit in $BHits){
$fruitMatches += [pscustomobject]@{Fruit=$BHit.Context.PostContext[3].Replace("name ",'');
Date=$BHit.Context.PostContext[0].Replace('p_date ','');
Time=$BHit.Context.PostContext[1].Replace('pt_time ','')}
}
#Resolve our Hits, looking in file A.txt for the line type FRUIT
$hits = select-string -Path $source -SimpleMatch "type FRUIT" -CaseSensitive -Context 2
ForEach ($hit in $hits){
$output += $fruitMatches | ? Fruit -eq ($hit.Context.PreContext[0].Replace('name','').Trim())
}
$output > $destination
Write-Output "Checking $destination for matches"
Get-content $destination
答案 1 :(得分:0)
纯批次解决方案:
@echo off
setlocal enabledelayedexpansion
REM create temporary numbered files:
findstr /n "^" a.txt >tempA.txt
findstr /n "^" b.txt >tempB.txt
(
REM search for "type FRUIT" and fetch (linenumber-2)
for /f "tokens=1 delims=: " %%a in ('findstr /c:"type FRUIT" tempA.txt') do (
set /a line=%%a-2
REM get content of this line:
for /f "tokens=1,3 delims=: " %%d in ('findstr /b "!line!:" tempA.txt') do (
REM get Fruit-linenumbers of B.txt:
for /f "tokens=1 delims=:" %%g in ('findstr /c:"name %%e" tempB.txt') do (
set /a line3=%%g-3
set /a line2=%%g-2
set /a line1=%%g-1
REM get the desired three lines from B.txt
for /f "tokens=1,* delims=:" %%j in ('findstr /b "!line3!: !line2!: !line1!: " tempB.txt') do (
echo %%k
)
)
)
echo.
)
)>done.txt
del temp?.txt
type done.txt
基本技巧是,在文件中添加行号,查找搜索字符串并计算所需行的元数。
答案 2 :(得分:0)
下面的批处理文件应该运行得很快,因为它只使用内部命令,但文件A.txt中最多只能包含1364个水果。如果您有更多,则可以修改该方法以使用辅助文件并使用findstr
进行处理,但在这种情况下,程序运行速度会变慢。
@echo off
setlocal EnableDelayedExpansion
rem Create list of fruit names from A.txt
set "list=/"
set "type="
for /F "tokens=1,2" %%a in (A.txt) do (
set "%%a=%%b"
if "!type!" equ "FRUIT" (
set "list=!list!!name!/"
set "type="
)
)
rem Extract 3 lines from B.txt
set "name="
(for /F "tokens=1*" %%a in (B.txt) do (
set "%%a=%%b"
for %%c in (!name!) do (
if "!list:/%%c/=!" neq "%list%" (
echo p_date !p_date!
echo pt_time !pt_time!
echo title !title!
echo/
set "name="
)
)
)) > done.txt
答案 3 :(得分:0)
具有下一个关键想法和/或限制的纯批次解决方案:
B.txt
文件视为具有特定水果(库存清单)的所谓独特外观;在这种情况下,输出特定水果的第一次出现; B.txt
文件(销售单列表)中特定水果的多个外观,请参阅下面的输出; A.txt
文件中的不同水果编号没有限制。荒谬的优势,当然难以理解甚至列举超过1364种水果:))剧本:
@ECHO OFF >NUL
SETLOCAL enableextensions disabledelayedexpansion
set "multipleFruitInBfile=%~1"
echo "name";"title";"p_date";"pt_time"> 29319122done.txt
for /F "tokens=1*" %%G in (29319122A.txt) do (
set "A%%G=%%H"
if /I "A%%G"=="Atype" if /I "%%H"=="FRUIT" (
call :forFruit
)
)
ENDLOCAL
type 29319122done.txt
goto :eof
:forFruit
SETLOCAL
for /F "tokens=1*" %%g in (29319122B.txt) do (
set "%%g=%%h"
if "%%g"=="name" if "%%h"=="%Aname%" (
call :forEcho
if "%multipleFruitInBfile%"=="" goto :eof
)
)
ENDLOCAL
goto :eof
:forEcho
echo "%name%";"%title%";"%p_date%";"%pt_time%">> 29319122done.txt
goto :eof
输出(在B.txt
文件中加倍 ORANG 记录):
==>D:\bat\29319122.bat
"name";"title";"p_date";"pt_time"
"APPLE";"sweet tasty apple";"10/03/15";"11:29:41:00"
"ORANG";"niice nice orange";"10/03/15";"11:29:43:00"
"CHERY";"nutritious rich fruit";"10/03/15";"11:29:44:00"
==>D:\bat\29319122.bat 1
"name";"title";"p_date";"pt_time"
"APPLE";"sweet tasty apple";"10/03/15";"11:29:41:00"
"ORANG";"niice nice orange";"10/03/15";"11:29:43:00"
"ORANG";"niice nice orange";"11/03/15";"11:29:45:00"
"CHERY";"nutritious rich fruit";"10/03/15";"11:29:44:00"
==>