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')
Related
I have a string like
"solrHost" : "http://localhost:8983,http://localhost:8764", in a file called sampple.json.
There could be space between "solrHost" and : or maybe not, and there could be space between : and "http://localhost:8983,http://localhost:8764"
I have a another variable
newServerName="http://newserver,http://newserver2"
The value of solrHost could be anything between double quotes,
I want to replace the value of solrHost from old to newServerName using sed can anyone help me here ?
You're much, much better off using a tool that understands JSON instead of trying to kludge together something with sed and regular expressions. jq is the go-to for command line manipulation of JSON:
$ cat foo.json
{
"solrHost" : "http://localhost:8983,http://localhost:8764",
"foo": 12
}
$ jq --arg url "http://newserver,http://newserver2" '.solrHost = $url' foo.json
{
"solrHost": "http://newserver,http://newserver2",
"foo": 12
}
sed 's%\("solrHost"[[:space:]]*:[[:space:]]*\)"[^"]*"%\1"'"$newServerName"'"%'
Use single quotes around most of the script.
Use % instead of / to mark the sections of the s/// (or s%%%) command.
Use [[:space:]]* to cover zero or more characters in the space class. Replace with just a blank-star if you don't care about the alternatives (tabs, etc), which is probably justifiable with well-formed JSON.
Capture the original "solrHost" part.
Be very careful with the quotes in the replacement.
"'"$newServerName"'"
The first double quote will appear in the replacement text.
The first single quote terminates the current single-quoted string.
The second double quote starts a new double-quoted string.
The replacement variable is next.
The third double quote ends the double-quoted string.
The second single quote starts a new (and rather short) single-quoted string.
The fourth double quote will appear in the replacement text.
Use below sed command to replace the text .
%s/solrHost(old name)/newServerName/g
I have a list of strings, and need to check each item to see if it contains some string $path, where the string should contain a unc path and $path is also a unc path.
For example:
"RW \\test" -match "\\test"
returns True, as \\test is contained in RW \\test. Great.
So why does this return False ? :
"RW \\test\te" -match "\\test\te"
At first I though maybe the single backslash is somehow acting as an escape character (even though in PowerShell that should be `)
So I tried
"RW \\test\\te" -match "\\test\\te"
But this also returns False ....
Why?
You need to escape both of the backslashes with backslashes in your regular expression on the right-hand side of the -match operator.
PS /> "RW \\test\te" -match "\\\\test\\te"
True
Here's what the result looks like:
PS /> $matches[0]
\\test\te
You could also expand on this to use named captures in regular expressions. Named captures just give friendly names to individual captures inside of a regular expression, making them more easily referenced as a property on the $matches variable, instead of a numeric index.
PS /> "RW \\test\te" -match "(?<UNCPath>\\\\test\\te)"
True
PS /> $matches.UNCPath
\\test\te
Keep in mind that the backtick character is used to escape certain special characters in PowerShell double-quoted strings. However, in the case of the -match operator, you're invoking the .NET regular expression engine. In the .NET regex engine, the backslash is used to escape special characters in the regex context. Hence, in this example, the backtick escape character isn't applicable.
Also, make sure that you are not escaping special characters in your source string, on the left-hand side of the -match operator. The reason that your final example doesn't match, is because you added a second \, but only escaped a single \ in the regex on the right-hand side of the -match operator.
To complement Trevor Sullivan's helpful answer with a tip provided by PetSerAl in a comment on the question:
To use a string as a literal in a regex context, pass it to [regex]::Escape():
PS> "RW \\test\te" -match [regex]::Escape("\\test\te")
True
[regex]::Escape() conveniently escapes all characters that have special meaning in a regex with escape character \, so that the string is matched as a literal:
PS> [regex]::Escape("\\test\te")
\\\\test\\te
Note how the \ instances were each escaped with \, effectively doubling them.
If your string does use regex constructs but also contains characters with special meaning in regexes that you want to be treated as literals, you must \-escape them individually:
PS> '***' -match '\**' # match zero or more (*) '*' chars (\*)
True
Somewhat orthogonal, but for matching paths, you might find the -like operator easier to use. It supports wildcards instead of regular expressions so you could write your example as
"RW \\test\te" -like "*\\test\te"
Note that the leading '*' on the RHS is required- wildcard patterns are "anchored" (have to match the whole string). Regular expressions are unanchored by default and only have to match a fragment of the string.
The problem
I have multiple property lines in a single string separated by \n like this:
LINES2="Abc1.def=$SOME_VAR\nAbc2.def=SOMETHING_ELSE\n"$LINES
The LINES variable
might contain an undefined set of characters
may be empty. If it is empty, I want to avoid the trailing \n.
I am open for any command line utility (sed, tr, awk, ... you name it).
Tryings
I tried this to no avail
sed -z 's/\\n$//g' <<< $LINES2
I also had no luck with tr, since it does not accept regex.
Idea
There might be an approach to convert the \n to something else. But since $LINES can contain arbitrary characters, this might be dangerous.
Sources
I skim read through the following questions
How can I replace a newline (\n) using sed?
sed with literal string--not input file
Here's one solution:
LINES2="Abc1.def=$SOME_VAR"$'\n'"Abc2.def=SOMETHING_ELSE${LINES:+$'\n'$LINES}"
The syntax ${name:+value} means "insert value if the variable name exists and is not empty." So in this case, it inserts a newline followed by $LINES if $LINES is not empty, which seems to be precisely what you want.
I use $'\n' because "\n" is not a newline character. A more readable solution would be to define a shell variable whose value is a single newline.
It is not necessary to quote strings in shell assignment statements, since the right-hand side of an assignment does not undergo word-splitting nor glob expansion. Not quoting would make it easier to interpolate a $'\n'.
It is not usually advisable to use UPPER-CASE for shell variables because the shell and the OS use upper-case names for their own purposes. Your local variables should normally be lower case names.
So if I were not basing the answer on the command in the question, I would have written:
lines2=Abc1.def=$someVar$'\n'Abc2.def=SOMETHING_ELSE${lines:+$'\n'$lines}
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 the following string ./test
and I want to replace it with test
so, I wrote the following in perl:
my $t =~ s/^.//;
however, that replaces ./test with /test
can anyone please suggest how I fix it so I get rid of the / too. thanks!
my $t =~ s/^\.\///;
You need to escape the dot and the slash.
The substitution is s/match/replace/. If you erase, it's s/match//. You want to match "starts with a dot and a slash", and that's ^\.\/.
The dot doesn't do what you expect - rather than matching a dot character, it matches any character because of its special treatment. To match a dot and a forward slash, you can rewrite your expression as follows:
my $t =~ s|^\./||;
Note that you are free to use a different character as a delimiter, in order not to confuse it with any such characters inside the regular expression.
If you want to get rid of ./ then you need to include both of those characters in the regex.
s/^\.\///;
Both . and / have special meanings in this expression (. is a regex metacharacter meaning "any character" and / is the delimiter for the s/// operator) so we need to escape them both by putting a \ in front of them.
An alternative (and, in my opinion, better) approach to the / issue is to change the character that you are using as the s/// delimiter.
s|^\./||;
This is all documented in perldoc perlop.
You have to use a backward slash before the dot and the forward slash: s/\.\//;
The backslash is used to write symbols that otherwise would have a different meaning in the regular expression.
You need to write my $t =~ s/^\.\///; (Note that the period needs to be escaped in order to match a literal period rather than any character). If that's too many slashes, you can also change the delimiter, writing instead, e.g., my $t =~ s:^\./::;.
$t=q(./test);$t=~s{^\./}{};print $t;
You need to escape the dot if you want it to match a dot. Otherwise it matches any character. You can choose alternate delimiters --- best when dealing with forward slashes lest you get the leaning-toothpick look when you otherwise need to escape those too.
Note that the dot in your question is matching any character, not a literal '.'.
my $t = './test';
$t =~ s{\./}{};
use Path::Class qw( file );
say file("./test")->cleanup();
Path::Class