在PowerShell中相当于* nix fold

时间:2015-01-30 19:51:22

标签: powershell powershell-v4.0

今天我有几百个项目(来自SQL查询的ID),需要将它们粘贴到另一个查询中以供分析师阅读。我需要* nix fold命令。我想采用300行并将它们重新格式化为每行由空格分隔的多个数字。我本来会用fold -w 100 -s

* nix上的类似工具包括fmtpar

在Windows上有一种简单的方法可以在PowerShell中执行此操作吗?我期望其中一个*-Format命令行完成,但我找不到它。我正在使用PowerShell v4。

请参阅https://unix.stackexchange.com/questions/25173/how-can-i-wrap-text-at-a-certain-column-size

# Input Data
# simulate a set of 300 numeric IDs from 100,000 to 150,000
100001..100330 | 
    Out-File _sql.txt -Encoding ascii

# I want output like:
# 100001,  100002,  100003,  100004,  100005, ... 100010, 100011
# 100012,  100013,  100014,  100015,  100016, ... 100021, 100021
# each line less than 100 characters.

5 个答案:

答案 0 :(得分:7)

根据文件的大小,您可以将其全部读入内存,将其与空格连接,然后拆分为100 *个字符或下一个空格

(Get-Content C:\Temp\test.txt) -join " " -split '(.{100,}?[ |$])' | Where-Object{$_}

那个正则表达式会查找100个字符,然后是第一个空格。然后该匹配为-split,但由于模式包含在括号中,因此返回匹配而不是丢弃。 Where删除匹配之间创建的空条目。

证明理论的小样本

@"
134
124
1
225
234
4
34
2
42
342
5
5
2
6
"@.split("`n") -join " "  -split '(.{10,}?[ |$])' | Where-Object{$_}

上面的内容尽可能分为10个字符。如果不能仍然保留数字。样本是基于我用我的头撞在键盘上。

134 124 1 
225 234 4 
34 2 42 
342 5 5 
2 6

然后你可以将它变成一个函数,以便获得你最想要的简单性。它可以变得更好,但这并不是答案的焦点。

Function Get-Folded{
    Param(
        [string[]]$Strings,
        [int]$Wrap = 50
    )
    $strings  -join " " -split "(.{$wrap,}?[ |$])" | Where-Object{$_}
}

再次使用样本

PS C:\Users\mcameron> Get-Folded -Strings (Get-Content C:\temp\test.txt) -wrap 40
"Lorem ipsum dolor sit amet, consectetur 
adipiscing elit, sed do eiusmod tempor incididunt 
ut labore et dolore magna aliqua. Ut enim 
ad minim veniam, quis nostrud exercitation 
... output truncated...

你可以看到它应该分成40个字符,但第二行更长。它在40之后分裂到下一个空格以保留这个词。

答案 1 :(得分:1)

如果它是每行一个项目,并且您希望将每100个项目连接到由空格分隔的单行上,则可以将所有输出放入文本文件中,然后执行以下操作:

gc c:\count.txt -readcount 100 | % {$_ -join " "}

答案 2 :(得分:1)

当我看到这个时,我想到的第一件事就是滥用Format-Table来做这件事,主要是因为它知道如何在指定宽度时正确地破坏线条。在提出一个函数后,似乎所提出的其他解决方案更短,可能更容易理解,但我认为我还是继续发布这个解决方案:

function fold {
    [CmdletBinding()]
    param(
        [Parameter(ValueFromPipeline)]
        $InputObject,
        [Alias('w')]
        [int] $LineWidth = 100,
        [int] $ElementWidth
    )

    begin {
        $SB = New-Object System.Text.StringBuilder

        if ($ElementWidth) {
            $SBFormatter = "{0,$ElementWidth} "
        }
        else {
            $SBFormatter = "{0} "
        }
    }

    process {
        foreach ($CurrentObject in $InputObject) {
            [void] $SB.AppendFormat($SBFormatter, $CurrentObject)
        }
    }

    end {
        # Format-Table wanted some sort of an object assigned to it, so I 
        # picked the first static object that popped in my head:
        ([guid]::Empty | Format-Table -Property @{N="DoesntMatter"; E={$SB.ToString()}; Width = $LineWidth } -Wrap -HideTableHeaders |
            Out-String).Trim("`r`n")
    }
}

使用它会得到如下输出:

PS C:\> 0..99 | Get-Random -Count 100 | fold
1 73 81 47 54 41 17 87 2 55 30 91 19 50 64 70 51 29 49 46 39 20 85 69 74 43 68 82 76 22 12 35 59 92 
13 3 88 6 72 67 96 31 11 26 80 58 16 60 89 62 27 36 37 18 97 90 40 65 42 15 33 24 23 99 0 32 83 14  
21 8 94 48 10 4 84 78 52 28 63 7 34 86 75 71 53 5 45 66 44 57 77 56 38 79 25 93 9 61 98 95          

PS C:\> 0..99 | Get-Random -Count 100 | fold -ElementWidth 2
74 89 10 42 46 99 21 80 81 82  4 60 33 45 25 57 49  9 86 84 83 44  3 77 34 40 75 50  2 18  6 66 13  
64 78 51 27 71 97 48 58  0 65 36 47 19 31 79 55 56 59 15 53 69 85 26 20 73 52 68 35 93 17  5 54 95  
23 92 90 96 24 22 37 91 87  7 38 39 11 41 14 62 12 32 94 29 67 98 76 70 28 30 16  1 61 88 43  8 63  
72                                                                                                  

PS C:\> 0..99 | Get-Random -Count 100 | fold -ElementWidth 2 -w 40
21 78 64 18 42 15 40 99 29 61  4 95 66  
86  0 69 55 30 67 73  5 44 74 20 68 16  
82 58  3 46 24 54 75 14 11 71 17 22 94  
45 53 28 63  8 90 80 51 52 84 93  6 76  
79 70 31 96 60 27 26  7 19 97  1 59  2  
65 43 81  9 48 56 25 62 13 85 47 98 33  
34 12 50 49 38 57 39 37 35 77 89 88 83  
72 92 10 32 23 91 87 36 41              

答案 3 :(得分:1)

这是我最终使用的。

# simulate a set of 300 SQL IDs from 100,000 to 150,000
100001..100330 | 
    %{ "$_, " } | # I'll need this decoration in the SQL script
    Out-File _sql.txt -Encoding ascii

gc .\_sql.txt -ReadCount 10 | %{ $_ -join ' ' }

感谢大家的努力和答案。我很惊讶在Rohn Edward的回答中没有使用Format-Table [guid]::Empty没有办法做到这一点。

我的ID比我给出的示例更加一致,所以Noah使用gc -ReadCount是迄今为止这个特定数据集中最简单的解决方案,但将来我可能会使用Matt的答案或答案由皇帝在评论中链接。

答案 4 :(得分:0)

我想出了这个:

$array = 
(@'
1
2
3
10
11
100
101
'@).split("`n") |
foreach {$_.trim()}

$array = $array * 40

$SB = New-Object Text.StringBuilder(100,100)

foreach ($item in $array) {

Try { [void]$SB.Append("$item ") }

Catch {
         $SB.ToString()
         [void]$SB.Clear()
         [Void]$SB.Append("$item ")
      }
}    
#don't forget the last line
$SB.ToString()

1 2 3 10 11 100 101 1 2 3 10 11 100 101 1 2 3 10 11 100 101 1 2 3 10 11 100 101 1 2 3 10 11 100 101 
1 2 3 10 11 100 101 1 2 3 10 11 100 101 1 2 3 10 11 100 101 1 2 3 10 11 100 101 1 2 3 10 11 100 101 
1 2 3 10 11 100 101 1 2 3 10 11 100 101 1 2 3 10 11 100 101 1 2 3 10 11 100 101 1 2 3 10 11 100 101 
1 2 3 10 11 100 101 1 2 3 10 11 100 101 1 2 3 10 11 100 101 1 2 3 10 11 100 101 1 2 3 10 11 100 101 
1 2 3 10 11 100 101 1 2 3 10 11 100 101 1 2 3 10 11 100 101 1 2 3 10 11 100 101 1 2 3 10 11 100 101 
1 2 3 10 11 100 101 1 2 3 10 11 100 101 1 2 3 10 11 100 101 1 2 3 10 11 100 101 1 2 3 10 11 100 101 
1 2 3 10 11 100 101 1 2 3 10 11 100 101 1 2 3 10 11 100 101 1 2 3 10 11 100 101 1 2 3 10 11 100 101 

也许不像你希望的那样紧凑,并且可能有更好的方法来做到这一点,但似乎有效。