Как мне отсортировать документ по подстроке в каждой строке на Win7?

1370
Joey Hammer

Как отсортировать текст по хэштегу в Windows-7?

У меня есть длинный текст (формат .txt), который выглядит примерно так:

  • Бла-бла # Тест
  • 123123 # Действительно
  • Бла бла # действительно
  • klfdmngl #Test

Я хотел бы удобно, быстро и автоматически сортировать текст так, чтобы он выглядел так:

  • Бла-бла # Тест
  • klfdmngl #Test
  • 123123 # Действительно
  • Бла бла # действительно

Я должен делать это ежедневно, поэтому я хотел бы иметь возможность сделать это за несколько шагов.

0
Кроме того, чтобы просто указать, какое программное обеспечение использовать, пожалуйста, определите точную процедуру. Joey Hammer 11 лет назад 1
Шаг 1: Заменить `#` на `, #` Шаг 2: Импортировать как CSV в Excel или аналогичное приложение. Der Hochstapler 11 лет назад 2
Your comment elsewhere says "so the script or whatnot has to be clever enough to work with long lines with line breaks" that is not a reliable delimiter? is the record delimiter a `#[sometext]`? horatio 11 лет назад 1
Пожалуйста, обновите ваш вопрос всей дополнительной информацией о формате входных файлов. martineau 11 лет назад 0
@ Оливер Зальцбург: Я думаю, что ОП также хотел бы знать, что делать после импорта в Excel или что-то еще? martineau 11 лет назад 0
@martineau: Извините, это не было решением, хотя оно и сработало для меня. Я не хотел бы рекомендовать кому-то использовать зверя, такого как Excel, для решения такой задачи. Вы, ребята, придумали гораздо лучшие примеры :) Der Hochstapler 11 лет назад 0

3 ответа на вопрос

1
Sean C.

Вот окончательное решение PowerShell, которое будет работать с новыми линиями. Предполагается, что разделитель является хэштегом, за которым следуют символы слова, за которыми следует . При наличии строки данных без хэш-тега предполагается, что данные продолжаются до следующей строки. Другая информация под этим разделом моего ответа не касается особого случая, упомянутого автором, когда данные пересекают границу новой строки. В этом примере предполагается, что файл называется test.txt и находится в текущем каталоге.

[string[]]$fileContent = (get-content .\test.txt); [string]$linebuffer = '';  [object]$fixedFile = foreach($line in $fileContent) { if(-not ($line -match "#\w+$")) { $linebuffer += ($line + ' '); continue; }  $linebuffer += $line; $linebuffer; $linebuffer = ''; }  ($fixedFile -replace '^(.*)\ (#.*)$', '$2 $1' | Sort-Object) -replace '^(#\w+)\ (.*)$','$2 $1' | out-file test.txt -encoding ascii 

Используйте gVim в Windows или MacVim в OS X.

ПРИМЕЧАНИЕ: Vim - это редактор с 2 режимами. Режим вставки / редактирования и командный режим. Чтобы на самом деле редактировать текст как обычный редактор, вы должны находиться в режиме редактирования, который требует нажатия клавиши, например aили i. Редактор запустится в командном режиме. В командном режиме вы можете просто начать с ввода двоеточия для ввода этих команд.

:%s/^\(.*\)\ \(\#\w\+\)$/\2\ \1/g :sort :%s/^\(\#\w\+\)\ \(.*\)$/\2\ \1/g 

Первая команда заменяет хэштегом в конце строки на начало строки. Вторая команда сортирует данные, а третья команда отменяет своп и перемещает хештег обратно в конец строки.

Я проверил это на вашем образце, и это работает.


@Oliver_Salzburg предоставил намного более простой ответ с помощью Excel в комментариях. Я не думал нестандартно и предоставил ответ с помощью текстового редактора.

Шаг 1. Замените #на ,#Шаг 2. Импортируйте как CSV в Excel или аналогичное приложение. - Оливер Зальцбург ♦


Вот решение, использующее только Powershell, которое можно сделать изначально на Win7. У меня до сих пор не было возможности прочитать про разрывы строк, поэтому это решение не учитывает их.

В этом примере предполагается, что файл, с которым вы работаете, является test.txt.

$tempstor = (get-content test.txt) -replace '^(.*)\ (#.*)$', '$2 $1' | Sort-Object $tempstor -replace '^(#\w+)\ (.*)$','$2 $1' | out-file test.txt -encoding ASCII 

Один вкладыш, рычаги суб-снарядов.

((get-content test.txt) -replace '^(.*)\ (#\w+)$', '$2 $1' | Sort-Object) -replace '^(#\w+)\ (.*)$','$2 $1' | out-file test.txt -encoding ascii 
(ОС: Win7). Я уже знал о решении Excel. Однако, поскольку я делаю это довольно часто (до десяти раз в день), неудобно продолжать конвертировать файл в CSV, открывать Excel, нажимать кнопки сортировки и т. Д. Возможно, есть способ создать командный файл ... В идеале Я просто хотел бы один раз щелкнуть, активировать скрипт или что-то, что обо всем позаботится и выведет в новый файл. Joey Hammer 11 лет назад 0
Еще одна вещь: некоторые из линий долго и может выглядеть следующим образом: blahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblah #hashtag - так скрипт или этажерку должен быть достаточно умен, чтобы работать с длинными линиями с разрывами строк. Joey Hammer 11 лет назад 0
That's also possible with vim, but it requires an additional switch on the end of the command to traverse line breaks. I'll update the original answer when I come up with the solution, it eludes my memory. Sean C. 11 лет назад 0
Another point, if you're interested in learning Vim, you can create user-defined functions and macros. This would allow you to enter a command like `:sorthash` for example and it would execute the commands in the proper sequence. Sean C. 11 лет назад 0
Я использую Dreamweaver нормально. У меня тоже есть копия Vim, но я не пользуюсь ею (вообще). Если бы эта проблема была решена в Vim, это было бы неплохо. Еще приятнее было бы, если бы я мог автоматически выполнить скрипт, чтобы мне фактически не приходилось открывать Vim и загружать файл каждый раз. Например, просто дважды щелкнув значок на рабочем столе, который выполняет сценарий или еще что-то, сортирует документ и сохраняет его под новым именем в выбранной папке. Joey Hammer 11 лет назад 0
If you install unxutils for windows if could be done with a script easily. `sed` and `sort` could do it. I'm at work at the moment and I've been called away. I'll update the answer with some scripted solutions when I've concluded my work. Sean C. 11 лет назад 0
Хорошо. У меня сейчас две папки на рабочем столе, bin и usr. Спасибо за помощь. Пожалуйста, дайте мне знать, когда у вас есть решение :) Joey Hammer 11 лет назад 0
Эх, Раджеш, он еще не дал полного решения. Joey Hammer 11 лет назад 0
I changed .\test.txt to c:\blah\blah\test.txt which seems to be ok but I get an error message for the last part of the script: PS C:\Users\Pongy> ($fixedFile -replace '^(.*)\ (#.*)$', '$2 $1' | Sort-Object) -replace '^(#\w+)\ (.*)$','$2 $1' | outf ile test.txt -encoding ascii The term 'outfile' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spe lling of the name, or if a path was included, verify that the path is correct and try again. Joey Hammer 11 лет назад 0
At line:1 char:105 + ($fixedFile -replace '^(.*)\ (#.*)$', '$2 $1' | Sort-Object) -replace '^(#\w+)\ (.*)$','$2 $1' | outfile <<<< test.t xt -encoding ascii + CategoryInfo : ObjectNotFound: (outfile:String) [], CommandNotFoundException + FullyQualifiedErrorId : CommandNotFoundException Joey Hammer 11 лет назад 0
@JoeyHammer Я сделал ошибку, которую исправил. `outfile` должен был быть` out-file`. Sean C. 11 лет назад 0
1
martineau

Вот командный файл Windows (.bat) или командный (.cmd), который это сделает. Я не был уверен, что вы хотите сделать с выводом, так что он просто отображает один из двух временных файлов, которые он создает, а затем удаляет оба из них.

@echo off if {%1} == {} ( echo usage: %0 ^<filename^> goto :EOF ) echo.>_temp1 for /F "tokens=1,2 delims=#" %%i in (%1) do echo %%j$%%i>>_temp1 echo.>_temp2 sort _temp1 >_temp2 echo.>_temp1 for /F "tokens=1,2 delims=$" %%i in (_temp2) do @echo %%j#%%i>>_temp1 type _temp1 del _temp1 del _temp2 
Это хорошее решение, но оно не обрабатывает разрывы строк, как упомянуто в комментариях к ответу, который я предоставил (второй комментарий). Sean C. 11 лет назад 0
@Sean C .: Из того, что было в комментарии, не было очевидно, что в строке произошел разрыв строки. Было бы лучше, если бы ОП обновил свой вопрос и лучше описал возможное содержимое входного файла. Интересно, было бы достаточно просто обнаружить, что строка не имеет `#`, чтобы предположить, что она была продолжена на следующей (или более). martineau 11 лет назад 0
Последнее предоставленное решение powershell ищет наличие хеш-тега в конце строки `/ # \ w + $ /`, если его не существует, предполагается, что данные продолжаются на следующей строке. Sean C. 11 лет назад 0
@SeanC .: Ответ / комментарий Оливера_Зальцбурга об импорте в Excel, скорее всего, также не будет обрабатывать прерывистые линии (без некоторого пользовательского кодирования VBA). Тем не менее, как и вы, я как бы выдыхаюсь в отношении этого недостаточно уточненного вопроса. martineau 11 лет назад 0
0
Der Hochstapler

Если вы работаете в Windows, вы можете использовать этот простой скрипт PowerShell:

[io.file]::ReadAllLines("test.txt")|Sort-Object {$_.SubString($_.IndexOf('#'))} 

Я не эксперт PowerShell, поэтому, извините, если есть более оптимальное решение :)

пример

Вот содержимое моего входного файла test.txt:

PS C:\Users\Oliver> type test.txt Blah blah #Test 123123 #Really Oliver #SuperUser Blah bluh #Really klfdmngl #Test 

Это вывод при запуске вышеуказанного скрипта:

PS C:\Users\Oliver> [io.file]::ReadAllLines("test.txt")|Sort-Object {$_.SubString($_.IndexOf('#'))} Blah bluh #Really 123123 #Really Oliver #SuperUser klfdmngl #Test Blah blah #Test 

Анализ

[io.file] # From the module io.file... ::ReadAllLines # use method ReadAllLines to read all text lines into an array... ("test.txt") # from the file test.txt  | # Take that array and pipe it to... Sort-Object # the cmdlet Sort-Object (to sort objects) { # To sort the elements in the array... $_.SubString( # use the part of the text line... $_.IndexOf('#') # that starts at the first position of a # )} 
@Oliver_Salzburg This solution does not handle the case where data spans multiple line breaks. See comment #2 in the answer I provided. Sean C. 11 лет назад 0
@Oliver_Salzburg Also, could you explain why you chose to use the .NET io.file class? Why not just use `get-content`? Your one-liner could easily have been `get-content test.txt | sort-object {$_.SubString($_.IndexOf('#'))}` Sean C. 11 лет назад 0
@SeanC .: Мой ответ относится к проблеме, поставленной в вопросе. Der Hochstapler 11 лет назад 0
@SeanC .: Потому что я больше знаком с классами .Net, чем с командлетами. Der Hochstapler 11 лет назад 0