I need to find this pattern, "LogEntry=", across multiple lines in the following file:
C:\test.conf
And change the line to read: "LogEntry=&MAC=" instead.
The script works fine so far to do that, but if someone runs the script twice it will re-add the same pattern, doubling it up.
I need to find a way to put a check in place to know if the file already has that pattern in it. Could someone please give me a hand with this one ?
Use negative lookahead in your regex e.g.:
'LogEntry=(?!&MAC=)'
That regex will not match the already modified line. Read more about look ahead/behind zero length assertions.
BTW if you have the PowerShell Community Extensions, you can do this edit operatio with a single command:
Edit-File C:\test.conf -Pattern 'LogEntry=(?!&MAC=)' -Replace 'LogEntry=&MAC='
And if you can't use PSCX's Edit-File, here is roughly the equivalent:
$content = Get-Content C:\test.temp
$content | Foreach {$_ -replace 'LogEntry=(?!&MAC=)','LogEntry=&MAC='} | Out-File -Encoding ASCII
I don't know what the file encoding is for your file. You need to know that and use the appropriate encoding on the Out-File command. If you don't specify the encoding, it defaults to Unicode.
Related
I want to find all files in a particular directory that contain a certain string. Specifically, I want to find the carriage return (\r) and then manually go through the files and remove occurrences of it. I don't want PowerShell to remove them because there may be certain subdirectories that require them in my directory structure.
Your question seems to boil down to: I want to find all files in a directory that contain the carriage return. Is there any reason why these answers are not adequate?
For example:
This should give the location of the files that contain your pattern:
Get-ChildItem -recurse | Select-String -pattern "dummy" | group path | select name
You could use Select-String to find patterns in a group of files, however this will only search for the pattern within each line of text. It will not work in your case because you want to search for the line separator.
An easier way is to use Get-Content, this converts a file to an array of strings, one item per line. Therefore any file that has a return and a line feed will produce an array with more than one item. Try something like this:
Get-ChildItem -recurse | ? {(Get-Content $_.FullName).count -gt 1}
If your files are quite large and you want to speed it up then add a -TotalCount like this:
Get-ChildItem -recurse | ? {(Get-Content $_.FullName -TotalCount 2).count -gt 1}
This will only find where the return and line feed are together, if you want instances where they could appear on their own then you will need to force Get-Content to not read the file as an array of strings but as one big string instead. Something like this:
Get-ChildItem -recurse | ? {[regex]::Matches((Get-Content $_FullName -Raw), '[\r\n]+').Count -gt 0}
I have a CSV file with text columns quoted in single quote around it and other non text columns don't have a quote around it.The text columns might have a comma or single quote within these single quoted text columns. I found a script online but it doesn't handle this kind of situation.
Is there way to handle this in PowerShell?
Example:
123,678.89,'hello there1', 'xyz1#gmail.com', 'abc,nds'\n
123,678.89,'hello 'there2', 'xyz2#gmail.com', 'akiu-'nds'\n
Output:
123,678.89|hello there1|xyz1#gmail.com|abc,nds \n
123,678.89|hello 'there2|xyz2#gmail.com|akiu-'nds \n
Example 2:
123,6272,678.89,,,'hello ,there1',,,,'abc1','tw,es',,'xyz1#gmail.com',,,,,,'abc,nds1'\n
124,8272,928.89,,,,'hello 'there2',,,'abc2','twes',,,'xyz2#gmail.com',,'biej',,,'abc'nds2'\n
125,9272,328.89,,'hello 'there3',,'abc3',', outyi',,,,'xyz3#gmail.com',,,,,,'ahct','abc'nds3'\n
Output:
123|6272|678.89|||hello ,there1||||abc1|tw,es||xyz1#gmail.com||||||abc,nds1\n 124|8272|928.89||||hello 'there2|||abc2|twes|||xyz2#gmail.com||biej|||abc'nds2\n
125|9272|328.89||hello 'there3||abc3|, outyi||||xyz3#gmail.com||||||ahct|abc'nds3\n
Similar to Kiran's answer. There are a couple of things that need to change so I don't think that there is a one size fits all solution. We need to chain these couple of changes. First being the commas that are actually delimiters and second the special end of line character sequence.
$path = "c:\temp\file.csv"
$newDelimiter = "|"
(Get-Content $path) -replace "'\s*?,\s?'|,\s?'|'\s?,",$newDelimiter -replace "'\s*?\\n$","\n" | Set-Content $path
I have a regex101 link that explains with more detail. The regex doing the greater work is the first with three potential alternate matches. This effectively ignores quotes that are off by themselves. If there is data that has a quote and comma combo then I think it would be following to program this without more information.
'\s*?,\s?': Comma enclosed in quotes optionally surrounded by variant white-space.
,\s?': Comma with optional space followed by a quote
'\s?,: Quote with optional space followed by a comma
So a match of any of the above groups would be replaced with $newDelimiter. Second regex is just looking for '\n$ while accounting for potential optional white-space between the quote and \n that happens at the end of the line. This is how the last single quote is removed.
something like this?
Get-Content C:\temp\file.txt |
ForEach-Object {$_ -replace ",'|',\s+'",'|' -replace "'\\n",' \n'} |
Set-Content C:\temp\newfile.txt
Note: the code is just one line, broken into 3 separate lines to read better.
I have multiple .mp3 files in the catalogue and want to remove artist's name from their filenames.
All the files' names contain string
"Adhesive Wombat - "
followed by the song's title.
I want to remove (not replace) every occurence of that specific string in every filename in current folder.
Not to mention, I've searched for answer on this site and failed to find an elegant and satisfying solution.
This is my first encounter with PowerShell.
As you know what you have is really close.
Dir | ren -NewName { $_.Name -replace "Adhesive Wombat - ", "" }
You added a stipulation that "Adhesive Wombat" may or may not contain a space. -replace uses regular expressions so lets harness that and make that space optional using a ?. I am also going to show you the full cmdlet name as supposed to aliases so you are aware of what is happening behind the scenes. It's hard to see but I tried to highlight the ? in bold for it to "pop".
Get-ChildItem | Rename-Item -NewName {$_.Name -replace "Adhesive ?Wombat - ", "" }
So that will match both
"other text Adhesive Wombat - other text "
"other text AdhesiveWombat - other text "
Also, depending on how much white space there is you could use \s+ where you have space which will match all consecutive white space.
From the above answers, the quick working example for simply copy&paste, that worked on win 10 Powershell:
change directory to your target directory
define files with e.g. *.txt or set all files with *.*
insert your Strings for replacement
cd C:\....
Get-ChildItem *.* | Rename-Item -NewName {$_.Name -replace "StringtoReplace", "newString"}
Complete novice here so all help gratefully recieved. I am hoping to edit a text file with a batch file.
I have a text file that is all one line.
I need the first 240 characters deleted
I need the last 82 characters deleted
Finally, anything in between I need each 100 characters to be separated with a line break
Thanks
Mark
try this (pure batch, no VBS):
#ECHO OFF &SETLOCAL
SET "longstring=012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789X012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789X0123456789012345678901234567890123456789012345678901234567890123456789012345678901"
ECHO %longstring%
ECHO(
REM I need the first 240 characters deleted
SET "longstring=%longstring:~240%"
ECHO %longstring%
ECHO(
REM I need the last 82 characters deleted
SET "longstring=%longstring:~0,-82%"
ECHO %longstring%
ECHO(
REM I need each 100 characters to be separated with a line break
SET LB=^
SET "right=%longstring%"
SET "longstring="
SETLOCAL ENABLEDELAYEDEXPANSION
:loop
SET "left=%right:~0,100%"
SET "right=%right:~101%"
SET "longstring=!longstring!!left!!LB!"
IF DEFINED right GOTO :loop
ECHO(!longstring!
..output is:
012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789X012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789X0123456789012345678901234567890123456789012345678901234567890123456789012345678901
X012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789X0123456789012345678901234567890123456789012345678901234567890123456789012345678901
X012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789X
X012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789X
Your problem is easily solved with nearly any programming language... except Windows batch :(
It is nearly impossible with Windows batch if your file is longer than 8192 bytes because batch variables are limited to 8192 characters. There is a complicated method that uses FC /B to effectively read one byte at a time, expressed as hex. It would be relatively easy to do the counting. But then each hex code would need to be converted back into the character value. You do not want to go through all that pain, except for maybe academic interest.
You could use PowerShell, VBScript, or JScript to easily do what you want.
But if you want to stick with batch, then you will need a non-standard utility to help you.
There are free utilities you could download that would make the solution trivial. For example, sed for Windows could make short work of this problem.
I have written a hybrid JScript/batch utility called REPL.BAT that performs regular expression search and replace on stdin, and writes the result to stdout. The utility is pure script that works on any Windows machine from XP onward - no exe download required. REPL.BAT is available here. Complete documentation is embedded within the script.
Assuming REPL.BAT is either in your current directory, or better yet, somewhere within your PATH, then the following simple batch script should do the trick. The script takes the name of the file to modify as the first and only argument. The file spec can include path information. Be sure to enclose the file in quotes if it contains spaces or other special characters.
#echo off
type %1|repl "^.{240}(.*).{82}$" "$1"|repl ".{100}" "$&\r\n" x >"%~1.mod"
move /y "%~1.mod" %1 >nul
I'd strongly recommend switching to PowerShell or at least VBScript if at all possible. It'd be a lot easier to do what you want with those languages.
PowerShell:
$filename = 'C:\path\to\your.txt'
(Get-Content $filename | Out-String) `
-replace '^[\s\S]{240}', '' `
-replace '[\s\S]{82}$','' `
-replace '([\s\S]{100})',"`$1`r`n" `
| Set-Content $filename
VBScript:
filename = "C:\path\to\your.txt"
Set fso = CreateObject("Scripting.FileSystemObject")
Set re = New RegExp
re.Global = True
txt = fso.OpenTextFile(filename).ReadAll
re.Pattern = "^[\s\S]{240}"
txt = re.Replace(txt, "")
re.Pattern = "[\s\S]{82}$"
txt = re.Replace(txt, "")
re.Pattern = "([\s\S]{100})"
txt = re.Replace(txt, "$1" & vbNewLine)
fso.OpenTextFile(filename, 2).Write txt
I have several php files in directory, I want to replace a few words in all files with different text. It's a part of my code:
$replacements_table=
("hr_table", "tbl_table"),
('$users', "tbl_users")
foreach ($file in $phpFiles){
foreach($replacement in $replacements_table){
(Get-Content $file) | Foreach-Object{$_ -replace $replacement} | Set-Content $file
}
}
It works fine for replacing "hr_table", but doesn't work at all for '$users'. Any suggestion would be nice
The string is actually a regular expression and so needs to be escaped using '\'. See this thread
$replacements_table= ("hr_table", "tbl_table"), ('\$users', "tbl_users")
will work.
The dollar sign is a special regular expression character, matches the end of a string, you need to escape it. Escaping a character in regex is done by a '\' in front of the character you want to escape. A safer method to escape characters (especially when you don't know if the string might contain special characters) is to use the Escape method.
$replacements_table= (hr_table', 'tbl_table'), ([regex]::Escape('$users'), 'tbl_users')
Try escaping "$' with a backslash: '\$users'
The $ symbol tells the regular expression to match at the end of the string. The backslash is the regular expression escape character.
try using double quotes around your variable name instead of single quotes
EDIT
Try something along these lines ....
$x = $x.Replace($originalText, '$user')