[英]Sort lines of a .txt file with PowerShell
我有一个像下面这样的.txt
:
MasterCard
R$ 66,12
Hipercard
R$ 7.501,98
MasterCard
R$ 48,19
Hipercard
R$ 7.742,46
MasterCard
R$ 48,19
Hipercard
R$ 5.846,14
MasterCard
R$ 48,19
Hipercard
R$ 4.210,65
Visa
R$ 4.210,65
MasterCard
R$ 48,19
Hipercard
R$ 2.892,20
MasterCard
R$ 48,19
Visa
R$ 4.210,65
Hipercard
R$ 1.944,19
Hipercard
R$ 584,04
Visa
R$ 4.210,65
我需要一个.bat
文件(可能在PowerShell中),该文件按描述和值来组织行,如下所示:
-----------------
MasterCard
R$ 66,12
MasterCard
R$ 48,19
MasterCard
R$ 48,19
MasterCard
R$ 48,19
MasterCard
R$ 48,19
MasterCard
R$ 48,19
----------------
Hipercard
R$ 7.501,98
Hipercard
R$ 7.742,46
Hipercard
R$ 5.846,14
Hipercard
R$ 4.210,65
Hipercard
R$ 2.892,20
Hipercard
R$ 1.944,19
Hipercard
R$ 584,04
--------------
Visa
R$ 4.210,65
Visa
R$ 4.210,65
Visa
R$ 4.210,65
.bat
文件有可能吗? 我被困在如何开始。 我正在尝试使用一个简单的命令: sort test.txt /o testout.txt
但这不起作用。
我有另一个主意。 运行此命令,我可以将所有行放在同一行中:
for /f "usebackq tokens=* delims=" %%a in ("frt01.txt") do (echo(%%a)>>test.txt
for /f "usebackqdelims=" %%i in ("test.txt") do @<nul set /p"=%%i ">>"test2.txt"
del test.txt /S /Q /
所以现在,描述和值都只在一行中:
MasterCard R$ 66,12 Hipercard R$ 7.501,98 MasterCard R$ 48,19 Hipercard R$ 7.742,46 MasterCard R$ 48,19 Hipercard R$ 5.846,14 MasterCard R$ 48,19 Hipercard R$ 4.210,65 MasterCard R$ 48,19 Hipercard R$ 2.892,20 MasterCard R$ 48,19 Hipercard R$ 1.944,19 Hipercard R$ 584,04
我该如何做才能像波纹管一样? (在每个值后键入“输入”)
MasterCard R$ 66,12
Hipercard R$ 7.501,98
MasterCard R$ 48,19
Hipercard R$ 7.742,46
MasterCard R$ 48,19
Hipercard R$ 5.846,14
MasterCard R$ 48,19
Hipercard R$ 4.210,65
MasterCard R$ 48,19
Hipercard R$ 2.892,20
MasterCard R$ 48,19
Hipercard R$ 1.944,19
Hipercard R$ 584,04
因为这样我可以使用以下命令进行sort test2.txt /o output.txt
: sort test2.txt /o output.txt
我想通过这种方式更容易。
@michael_heath这是我在说的:
Hipercard R$ 584,04
Hipercard R$ 1.944,19
Hipercard R$ 2.892,20
Hipercard R$ 4.210,65
Hipercard R$ 5.846,14
Hipercard R$ 7.501,98
Hipercard R$ 7.742,46
------------------------
MasterCard R$ 48,19
MasterCard R$ 48,19
MasterCard R$ 48,19
MasterCard R$ 48,19
MasterCard R$ 48,19
MasterCard R$ 66,12
------------------------
Visa R$ 48,19
Visa R$ 48,19
Visa R$ 48,19
------------------------
在对数据进行排序之前,您需要对其进行解析。 您可以将ConvertFrom-String
cmdlet与模板一起使用来执行此操作:
$Template = @'
{CardProvider*:MasterCard}
R$ {Amount:66,12}
{CardProvider*:Hipercard}
R$ {Amount:7.501,98}
{CardProvider*:Visa}
R$ {Amount:4.210,65}
'@
$Transactions = Get-Content path\to\file.txt |ConvertFrom-String -TemplateContent $Template
$Transactions
变量现在将包含一个对象数组,每个对象都具有CardProvider
和Amount
属性。 要按提供者排序,然后按金额排序,我们可以执行以下操作:
# Define output file name
$OutputFile = 'output.txt'
# Group by card type first
$Transactions |Group-Object CardProvider |ForEach-Object {
# Write seperator to output file:
'----------------' |Add-Content -Path $OutputFile
# Now we sort each group of cards by descending amount
$_.Group |Sort-Object {$_.Amount -replace '\.' -replace ',','.' -as [decimal]} -Descending |ForEach-Object {
# Finally write the contents to file again
$_.CardProvider,"R$ $($_.Amount)","" |Add-Content -Path $OutputFile
}
}
所有批处理文件代码
选项1
@echo off
setlocal enabledelayedexpansion
(
for /f "tokens=1,2" %%A in (frt01.txt) do (
if not "%%~A" == "R$" (
set "card=%%~A "
set "card=!card:~,11!"
) else (
set "value= %%~B"
set "value=!value:~-9!"
echo !card! %%~A !value!
)
)
) > unsorted.txt
sort unsorted.txt /o output.txt
rem Optional code below to insert ------- between rows after sort.
set "last_card="
(
for /f "delims=" %%A in (output.txt) do (
for /f %%B in ("%%~A") do set "card=%%~B"
if defined last_card if not "!card!" == "!last_card!" (
echo ------------------------
)
echo %%A
set "last_card=!card!"
)
echo ------------------------
) > tmp.txt
move /y tmp.txt output.txt
这是延迟扩展的概念。 使用固定的间距,以便在不同长度的卡和货币值的情况下可以更好地sort
。
for /?
用于令牌描述等 set /?
用于使用的替换语法,即set "card=!card:~,11!"
。 选项2
@(
@echo off
setlocal enabledelayedexpansion
for /f "tokens=1,2" %%A in (frt01.txt) do (
if not "%%~A" == "R$" (
set "card=%%~A "
call set "card=%%card:~,11%%"
) else (
set "value= %%~B"
call set "value=%%value:~-9%%"
call echo "%%card%%" "%%A" "%%value%%"
)
)
) | sort /o output.txt
这是一个不寻常的概念。 像以前的代码一样,使用固定的间距。 它不使用临时文件,因为它通过管道直接进行sort
。
使用setlocal enabledelayedexpansion
即使没有!
被使用。 延迟变量不会扩展。 如果没有延迟扩展,则call set
和call echo
将无法工作。
可在Win7上运行,尽管也许奇怪的行为可能会使其他代码成为更好的选择。
选项3
@echo off
setlocal
if not "%~1" == "" (
if "%~1" == "/?" goto :help
for %%A in (%*) do call :read "%%~A"
exit /b
)
rem If no arguments, do this optional task instead.
> "%~dp0unsorted.txt" call :read "frt01.txt"
sort "%~dp0unsorted.txt" /o "%~dp0output.txt"
del "%~dp0unsorted.txt"
exit /b
:read
setlocal enabledelayedexpansion
for /f "usebackq tokens=1,2" %%A in ("%~1") do (
if not "%%~A" == "R$" (
set "card=%%~A "
set "card=!card:~,11!"
) else (
set "value= %%~B"
set "value=!value:~-9!"
echo !card! %%~A !value!
)
)
exit /b
:help
echo Prints Hipercard, MasterCard... vertical list as 3 horizontal fixed columns.
echo If multiple files are passed as arguments, they will be printed in sequence.
echo.
echo Syntax: %~nx0 file [file [file]]
echo.
echo Examples:
echo %~nx0 "test 1.txt"
echo %~nx0 test1.txt test2.text ^| sort /o output.txt
exit /b
这是rem
备注行下方的独立脚本或运行代码。 您可以删除可选代码并将脚本放置在PATH中,以便可以从任何地方的控制台运行它。
如果脚本名为cardsorter.cmd,则可以
cardsorter frt01.txt | sort /o output.txt
在命令提示符下。
所有选项的输出
Hipercard R$ 584,04
Hipercard R$ 1.944,19
Hipercard R$ 2.892,20
Hipercard R$ 4.210,65
Hipercard R$ 5.846,14
Hipercard R$ 7.501,98
Hipercard R$ 7.742,46
MasterCard R$ 48,19
MasterCard R$ 48,19
MasterCard R$ 48,19
MasterCard R$ 48,19
MasterCard R$ 48,19
MasterCard R$ 66,12
Visa R$ 4.210,65
Visa R$ 4.210,65
Visa R$ 4.210,65
注意
选项1插入--------------
以分隔卡类型。
这是一个批处理文件解决方案。 要将行堆叠在一起,您只需使用变量来保留前一行。
@echo off
setlocal enabledelayedexpansion
set "line1="
(FOR /F "delims=" %%G IN (input.txt) DO (
IF NOT DEFINED line1 (
set "line1=%%G
) else (
echo !line1! %%G
set "line1="
)
))>temp.txt
sort temp.txt>output.txt
以下代码将输入文件解析为事务对象的数组,对它们进行排序,然后输出排序后的数组。 并不是说金额是按右对齐的字符串排序的。
$unsortedtransactions = @()
Get-Content .\in.txt -ReadCount 3 |
ForEach-Object {
$Matches = $null
"$_" -match '([^\s]*)\s*(\S*)\s*(.*)$(.*)$' | Out-Null
$thisrecord = [PSCustomObject] @{ Card = $Matches[1]
Currency = $Matches[2]
Amount = $("{0,15}" -f @($Matches[3].Trim()))
}
$unsortedtransactions += $thisrecord
}
$sortedtransactions = $unsortedtransactions | Sort-Object -Property Card, Currency, Amount
foreach ($t in $sortedtransactions) {
$("{0}`r`n{1} {2}`r`n" -f @($t.Card, $t.Currency, $t.Amount.Trim())) |
Out-File -FilePath st.txt -Encoding ascii -Append
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.