簡體   English   中英

使用PowerShell對.txt文件的行進行排序

[英]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.txtsort 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變量現在將包含一個對象數組,每個對象都具有CardProviderAmount屬性。 要按提供者排序,然后按金額排序,我們可以執行以下操作:

# 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 setcall 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM