如何在wincmd或powershell中将我的txt文件输出格式化为excel

时间:2016-12-30 10:49:57

标签: powershell batch-file cmd

我有一个带有以下输出的.txt,需要在excel中使用列名作为"名称,ID,位置,角色"以下各行的详细信息。

Name: Murali
ID: 485
location: Trichy
Role: AS
Name: John
ID: 584
location: NY
Role: AS
Name: Oisce
ID: 358
location: NBC
Role: AS

提前致谢!!

3 个答案:

答案 0 :(得分:3)

以下是通用PowerShell v3 +解决方案,适用于任何数字的任何字段名称(假设这些行以相同的顺序重复相同的字段名称); 将输入直接转换为可在Excel中打开的CSV文件

# Determine input and output file.
$inFile = 'file.txt'
$outFile = 'file.csv'

# Extract the headers from the input file, using an ordered hashtable.
# Lines are read, and each line's 1st field is added as a key to the hashtable
# until a duplicate value is found in the 1st field.
$headers = [ordered] @{}
foreach($line in (Get-Content $inFile)) {
  $colName = ($line -split ': ', 2)[0]
  if ($headers.Contains($colName)) { break }
  $headers.$colName = $null
}

# Construct the header row and send it to the output file.
# Choose a suitable character encoding.
"`"$($headers.Keys -join '","')`"" | Out-File -Encoding Utf8 $outFile

#`# Now loop over all lines and write the data rows.
$numCols = $headers.Count
$outLine = ''
$sep = ''
$i = 0
foreach($line in (Get-Content $inFile)) {
  ++$i # Count lines starting at 1.
  $val = ($line -split ': ', 2)[1]
  # Enclose the value in "...", if necessary.
  if ($val -match '[ ,"]') { $val = "`"$($val -replace '"', '\"')`"" }
  #`# Add to the output line at hand.
  $outLine += $sep + $val
  if ($i % $numCols -eq 0) { # Last column value.
    # Complete output line assembled, append it to the file.
    # Note that the -Encoding value must match the one above.
    $outLine | Add-Content -Encoding Utf8 $outFile
    $sep = ''
    $outLine = ''
  } else { # 1st or interior column value
    $sep = ','
  }
}

答案 1 :(得分:0)

无需在Excel中格式化,只需将字段与字符分隔即可,或者; (取决于您在Excel中的语言设置)并将文件重命名为具有扩展名.csv,例如“data.csv”。

当您从资源管理器中打开文件时,Excel将打开此文件并按列和行排列数据。您可以在Excel中格式化布局并将其另存为XLSX文件。

此处您的数据格式为CSV,并带有<分隔符

Name, id, location, role
Murali, 485, Trichy, AS
John, 584, NY, AS
Oisce, 358, NBC, AS
编辑:由于mklement0的挑战,这里是一个单行的Ruby解决方案,而不是回答的一部分,我肯定不是最短或最好的解决方案,只是一个概念证明

%(
Name: Murali
ID: 485
location: Trichy
Role: AS
Name: John
ID: 584
location: NY
Role: AS
Name: Oisce
ID: 358
location: NBC
Role: AS
).scan(/(^\w+):( \w+)/).transpose.each_with_index.map{|r,i|i==0 ? r.uniq.collect{|x| %("#{x.strip}") }.join(',') : r.each_slice(4).map{|s|s.collect{|x| %("#{x.strip}") }.join(',')}}.join("\n")

这里按操作分解

s.scan(/(^\w+):( \w+)/) # array of arrays (key, value), based on regular expression
 .transpose.each_with_index.map{|r,i| # transpose to array of headers and values, use Enumerator
   i==0 ? # first line = headers
   r.uniq.collect{|x| %("#{x}") }.join(',') # unique values, surround with "", join with ","
   : # rest of the lines = data
   r.each_slice(4).map{|s| # pieces of 4 items
     s.collect{|x| %("#{x.strip}") } # surround with ""
     .join(',')}} # join with ","
 .join("\n") # join with new line char

或更短的变体(s包含要解析的字符串)

(s.lines[0..3].join.scan(/(^\w+): (\w+)/).transpose.first + s.lines.join.scan(/(^\w+): (\w+)/).transpose.last).each_slice(4).map{|a| %("#{a.join('","')}")}

EDIT2: 从文件中读取就像Fire.read("data.txt").scan(..)等一样简单。

如果有必要,我可以读取内存GB中的文件但是Ruby有懒惰的方法,只读取当前需要的部分。 您也可以使用例如File.foreach('data.txt').first(10),它在第10行读取时停止。 但是不想让它过于复杂。 参见例如http://blog.honeybadger.io/using-lazy-enumerators-to-work-with-large-files-in-ruby/

答案 2 :(得分:0)

这是一个纯粹的解决方案;提供文本文件以重新格式化为命令行参数:

@echo off
setlocal EnableExtensions DisableDelayedExpansion

rem // Define constants here:
set "_FILES=%~1"

for /F "delims== eol==" %%E in ('2^> nul set $') do set "%%E="

for %%F in ("%_FILES%") do (
    if /I "%%~xF"==".csv" (set "EXT=_NEW.csv") else set "EXT=.csv"
    set "FLAG=#"
    < "%%~F" set /P LONE=""
    set "FILE=%%~F"
    setlocal EnableDelayedExpansion
    > "%%~dpnF!EXT!" (
        for /F "tokens=1,* delims=: eol=:" %%K in ('type "!FILE!" ^& echo^(!LONE!') do (
            endlocal
            set "HEAD=%%K"
            set "DATA=%%L"
            if defined FLAG set "FLAG=,"
            set "LINE=,"
            setlocal EnableDelayedExpansion
            if defined $!HEAD! (
                for /F "tokens=1,* delims== eol==" %%G in ('set $') do (
                    endlocal
                    set "NAME=%%G"
                    set "ITEM=%%H"
                    setlocal EnableDelayedExpansion
                    for /F "tokens=1,* delims=: eol=:" %%E in ("!FLAG!"!NAME:*$^=!",:!LINE!"!ITEM!",") do (
                        endlocal
                        if defined FLAG set "FLAG=%%E"
                        set "LINE=%%F"
                        setlocal EnableDelayedExpansion
                    )
                )
                if defined FLAG (
                    echo(!FLAG:~1,-1!
                    echo(!LINE:~1,-1!
                    endlocal
                    set "FLAG="
                ) else (
                    echo(!LINE:~1,-1!
                    endlocal
                )
                for /F "delims== eol==" %%E in ('set $') do set "%%E="
                setlocal EnableDelayedExpansion
            )
            if "!DATA:~,1!"==" " set "DATA=!DATA:~1!"
            for /F "delims=" %%E in ("$!HEAD!=!DATA!") do (
                endlocal
                set "%%E"
                setlocal EnableDelayedExpansion
            )
        )
    )
    endlocal
)

endlocal
exit /B

使用输入文件的输出CSV文件如下所示:

"ID","location","Name","Role"
"485","Trichy","Murali","AS"
"584","NY","John","AS"
"358","NBC","Oisce","AS"

更新

以下是脚本的改进版本,它保留了首次出现在输入文件中的字段的原始顺序:

@echo off
setlocal EnableExtensions DisableDelayedExpansion

rem // Define constants here:
set "_FILES=%~1"
set "_RSLTS=%~2"

rem // Clear all dynamic variables:
for /F "delims==" %%E in ('2^> nul set #') do set "%%E="
for /F "delims==" %%E in ('2^> nul set $') do set "%%E="

rem // Loop through the given file(s) to resolve its/their path(s):
for %%F in ("%_FILES%") do (
    if /I "%%~xF"==".csv" (set "FEXT=_NEW.csv") else set "FEXT=.csv"
    set "FLAG=#"
    < "%%~F" set /P LONE=""
    set "FILE=%%~F"
    set "RSLT=%%~dpnF"
    set /A "IDX=0"
    setlocal EnableDelayedExpansion
    if defined _RSLTS (set "RSLT=con") else set "RSLT=!RSLT!!FEXT!"
    rem // Write to output file all at once:
    > "!RSLT!" (
        rem /* Read input file line by line, repeat first line once again finally, because
        rem    this contains an already present header for sure and therefore initiates
        rem    returning the previously collected last output data row: */
        for /F "tokens=1,* delims=: eol=:" %%K in ('type "!FILE!" ^& echo^(!LONE!') do (
            endlocal
            set "HEAD=%%K"
            set "DATA=%%L"
            if defined FLAG set "FLAG=,"
            set "LINE=,"
            set /A "IDX+=1"
            setlocal EnableDelayedExpansion
            rem /* Check if current header is already present; if so, begin collecting a
            rem    new data row and return the previously collected one: */
            if defined $!HEAD! (
                rem // Read dynamic variable corresponding to current header indirectly:
                for /F "tokens=1,* delims==" %%G in ('set #') do (
                    for /F "tokens=1,* delims=:" %%E in ("!FLAG!"%%H",:!LINE!"!$%%H!",") do (
                        endlocal
                        if defined FLAG set "FLAG=%%E"
                        set "LINE=%%F"
                        setlocal EnableDelayedExpansion
                    )
                )
                rem /* Return the currently collected data row, together with the column
                rem    header row in case it is the first time: */
                if defined FLAG (
                    echo(!FLAG:~1,-1!
                    echo(!LINE:~1,-1!
                    endlocal
                    set "FLAG="
                ) else (
                    echo(!LINE:~1,-1!
                    endlocal
                )
                rem // Clear all dynamic variables:
                for /F "delims==" %%E in ('set #') do set "%%E="
                for /F "delims==" %%E in ('set $') do set "%%E="
                set /A "IDX=1"
                setlocal EnableDelayedExpansion
            )
            rem // Remove leading white-spaces from data value:
            for /F "tokens=* eol= " %%E in ("!DATA!") do (
                endlocal
                set "DATA=%%E"
                setlocal EnableDelayedExpansion
            )
            rem /* Assign name of dynamic variable corresponding with current header to a
            rem    numeric dynamic variable for preserving the order of (first) headers: */
            set "IDX=000!IDX!"
            for /F "delims=" %%E in ("#!IDX:~-4!=!HEAD!") do (
                endlocal
                set "%%E"
                setlocal EnableDelayedExpansion
            )
            rem // Assign data value to dynamic variable corresponding with current header:
            for /F "delims=" %%E in ("$!HEAD!=!DATA!") do (
                endlocal
                set "%%E"
                setlocal EnableDelayedExpansion
            )
        )
    )
    endlocal
)

endlocal
exit /B

使用输入文件的输出CSV文件如下所示:

"Name","ID","location","Role"
"Murali","485","Trichy","AS"
"John","584","NY","AS"
"Oisce","358","NBC","AS"