BAT or Powershell For loop through CSV to build a URL - batch-processing

Solved. So my first go at this post was a VERY poorly structured question trying to obfuscate proprietary company information in a very poor manner, and not asking the question well.
Once Walter even got me thinking in the correct direction i worked through the issue. Below was the second issue i was running into and found that the #{key=value} statement was being passed into my url because for some reason my script did not like the header in my csv file. In hindsight, perhaps because i was naming my variable the same as my header. Regardless I worked around it just by using Get-Content rather than Import-CSV.
$aliases = Import-Csv -Path .\aliases.csv
foreach ($alias in $aliases) {
Write-Output ('http://www.' + $($alias) + '.mydomain.com') >> urls.txt
where the contents of aliases.csv is:
alias
Matthew
Mable
Mark
Mary
This is giving me:
http://www.#{alias=Matthew}.mydomain.com
http://www.#{alias=Mable}.mydomain.com
http://www.#{alias=Mark}.mydomain.com
http://www.#{alias=Mary}.mydomain.com
When successful urls.txt should contain:
http://www.Matthew.mydomain.com
http://www.Mable.mydomain.com
http://www.Mark.mydomain.com
http://www.Mary.mydomain.com
NOTE: Edited to clarify use case

In Powershell
Get-Content names.txt | %{"Hello, my name is $_. How are you?"} >> results.txt
By the way, with just a little more effort, you can read more than one variable from a csv file, and substitute all of them for named variables in the text. This turns out to be very useful in a variety of situations.
Edit to conform to your edit
Import-csv ./aliases.csv | %{ "http://www.$($_.alias).mydomain.com"}
Notes:
Once you get used to them, pipelines are the easiest way to process a stream of just about anything.
% is an abbreviation of Foreach-Object (not to be confused with foreach).
The loop will be done once for each object coming out of the pipe. Each object will be a PSCustomObject with a single property named alias.
$() allows evaluation of a subexpression within a double quoted string.
$_ is the current object.
the dot, in this context, separates an object specified from a named property.

Related

How to edit a .property file in powershell

I have a application.properties file in following format
application.name=some thing
application.version=4.1.0.1
application.list=abc.def, ghi.jkl
Now my task is to append mno.pqr to application.list
I am able to read it using
$AppProps = convertfrom-stringdata (get-content .\application.properties -raw)
I changed the Application.list value in $AppProps.
How to save it back to original Application.properties file..?
You can try the following:
$AppProps.GetEnumerator() | % { "$($_.Name)=$($_.Value)" } > .\application.properties
Note that > creates UTF-16 LE files (with BOM) by default, so if you want to control the encoding explicitly, pipe to either Out-File or Set-Content using the -Encoding parameter instead.
There is no complementary ConvertTo-StringData, unfortunately, so you have to create your own output formatting (the default output format of a hashtable does not work as a properties file):
ConvertFrom-StringData returns a hashtable, so $AppProps contains one.
$AppProps.GetEnumerator() sends the hashtable's key/value pairs (dictionary entries of type [System.Collections.DictionaryEntry]) one by one through the pipeline.
The .GetEnumerator() call is necessary, because PowerShell treats a hashtable as a single object in a pipeline.
% { "$($_.Name)=$($_.Value)" } constructs the output string for each key/value pair.
Caveats that stem from using ConvertFrom-StringData to read properties files:
Loss of ordering: Since key ordering is not guaranteed in a hashtable, the properties will typically appear in different order when you rewrite the file (at least the first time).
Loss of comments: Comments in the input file (lines whose first non-blank char. is #) are quietly skipped on reading, so you'll lose them when you rewrite the file.

Changing a string in an .exe file

I would like to know how to change a String in an .exe file. It is a list of 8 files which have all the same Content but are used in diferent paths. And These paths (Folders) are named 1-8. And now I have to Change that string ("word class 1") into 2-8 ("word class 2, ...") I did it manually with Notepad++ for a week now but it's time consuming and I don't want to do it anymore with Notepad++. :)
I don't mind any way of a solution to this Problem so, that's it.
I tried it with powershell so far but I can't figure out how to get the solution done with the get-content & select_string but it didn't work out as intended.
Thank you for reading and answering my question. (sorry for some typos)
You just want to replace some values within a .exe?
This is how I'd do it.
You need to provide a CSV file, first column titled OLD, second column titled new.
Here is my fake .exe file I made:
7deeadc7-a2b3-4c47-8cf6-61f09d986977ham
d1ea8982-4a04-4f2b-8e5a-244965921fccsam
b4a8f37a-c607-405b-8493-9b9b0e79673btam
0922496b-3064-4958-a6b0-46f61a711860turkey
e5f30554-e50e-4b61-aaa3-3797d9e0ed5ccheese
82e3d77f-53d5-49ef-bf84-b872dbbe556ffork
60a01cad-f6c4-44cc-af1a-fafb20377a12rice
e2cd71a1-7c34-456f-9af4-924f79874c38yummy
c85da055-c47e-41be-a0f8-5c320fa05317linux
7dbee5fc-87d5-4900-80c5-00818514d5b4morp
d9941dfe-dd97-422d-9088-2cecf4904fdepoo
05eaf9b3-09a2-45ea-b9a0-4c78ff9156f2pot
8c75d00d-4157-45b9-86df-74226790674fpoe
f0e77eb5-35fa-47f5-b89e-d1b5ef3c726fpoh
1d1ffc02-fee0-446d-aeac-940ab2864a76pof
Just a bunch of guids with a word at the end. Now, Here's my sample .csv file, with all of the replacements we want to make.
OLD,NEW
ham,pork
sam,Frodo
linux,Window
morp,porp
poo,restroom
Finally, here is the code to do this as a PowerShell Function.
Function Refresh-File {
param($inputCSV,$inputfile)
$file = get-content $inputfile
Foreach ($replacement in (Import-csv $inputCSV)){
$file = $file -replace $replacement.old,$replacement.New
}
$file | set-content $inputfile
}
Call it like this: Refresh-File -inputCSV T:\replace.csv -inputfile T:\blah.exe
Here's my .exe file after running this, just the value portions, to show you that it worked:
pork
Frodo
tam
turkey
cheese
fork
rice
yummy
Window
porp
restroom
pot
poe
poh
pof
Since you'll want to automate this, simply make a new replacement.csv file everyday. Then run this code. If you've never written a full PS1 script file before, as a quick summary, copy the function, paste it into notepad or the PowerShell ISE, and then at the last line of the script, put the command syntax to call the function. Save and enjoy.

Buffering output with AWK

I have an input file which consists of three parts:
inputFirst
inputMiddle
inputLast
Currently I have an AWK script which with this input creates an output file which consists of two parts:
outputFirst
outputLast
where outputFirst and outputLast is generated (on the fly) from inputFirst and inputLast respectively. However, to calculate the outputMiddle part (which is only one line) I need to scan the entire input, so I store it in a variable. The problem is that the value of this variable should go in between outputFirst and outputLast in the output file.
Is there a way to solve this using a single portable AWK script that takes no arguments? Is there a portable way to create temporary files in an AWK script or should I store the output from outputFirst and outputLast in two variables? I suspect that using variables will be quite inefficient for large files.
All versions of AWK (since at least 1985) can do basic I/O redirection to files or pipelines, just like the shell can, as well as run external commands without I/O redirection.
So, there are any number of ways to approach your problem and solve it without having to read the entire input file into memory. The most optimal solution will depend on exactly what you're trying to do, and what constraints you must honour.
A simple approach to the more precise example problem you describe in your comment above would perhaps go something like this: first in the BEGIN clause form two unique filenames with rand() (and define your variables), then read and sum the first 50 numbers from standard input while also writing them to a temporary file, then continuing to read and sum the next 50 numbers and write them to a second file, then finally in an END clause you would use a loop to read the first temporary file with getline and write it to standard output, print the total sum, then read the second temporary file the same way and write it to standard output, and finally call system("rm " file1 " " file2) to remove the temporary files.
If the output file is not too large (whatever that is), saving outputLast in a variable is quite reasonable. The first part, outputFirst, can (as described) be generated on the fly. I tried this approach and it worked fine.
Print the "first" output while processing the file, then write the remainder to a temporary file until you have written the middle.
Here is a self-contained shell script which processes its input files and writes to standard output.
#!/bin/sh
t=$(mktemp -t middle.XXXXXXXXX) || exit 127
trap 'rm -f "$t"' EXIT
trap 'exit 126' HUP INT TERM
awk -v temp="$t" "NR<500000 { print n+1 }
{ s+=$1 }
NR>=500000 { print n+1 >>temp
END { print s }' "$#"
cat "$t"
For illustration purposes, I used really big line numbers. I'm afraid your question is still too vague to really obtain a less general answer, but perhaps this can help you find the right direction.

Best practice using NSLocalizedString

I'm (like all others) using NSLocalizedStringto localize my app.
Unfortunately, there are several "drawbacks" (not necessarily the fault of NSLocalizedString itself), including
No autocompletition for strings in Xcode. This makes working not only error-prone but also tiresome.
You might end up redefining a string simply because you didn't know an equivalent string already existed (i.e. "Please enter password" vs. "Enter password first")
Similarily to the autocompletion-issue, you need to "remember"/copypaste the comment strings, or else genstring will end up with multiple comments for one string
If you want to use genstring after you've already localized some strings, you have to be careful to not lose your old localizations.
Same strings are scattered througout your whole project. For example, you used NSLocalizedString(#"Abort", #"Cancel action") everywhere, and then Code Review asks you to rename the string to NSLocalizedString(#"Cancel", #"Cancel action") to make the code more consistent.
What I do (and after some searches on SO I figured many people do this) is to have a seperate strings.h file where I #define all the localize-code. For example
// In strings.h
#define NSLS_COMMON_CANCEL NSLocalizedString(#"Cancel", nil)
// Somewhere else
NSLog(#"%#", NSLS_COMMON_CANCEL);
This essentially provides code-completion, a single place to change variable names (so no need for genstring anymore), and an unique keyword to auto-refactor. However, this comes at the cost of ending up with a whole bunch of #define statements that are not inherently structured (i.e. like LocString.Common.Cancel or something like that).
So, while this works somewhat fine, I was wondering how you guys do it in your projects. Are there other approaches to simplify the use of NSLocalizedString? Is there maybe even a framework that encapsulates it?
NSLocalizedString has a few limitations, but it is so central to Cocoa that it's unreasonable to write custom code to handle localization, meaning you will have to use it. That said, a little tooling can help, here is how I proceed:
Updating the strings file
genstrings overwrites your string files, discarding all your previous translations.
I wrote update_strings.py to parse the old strings file, run genstrings and fill in the blanks so that you don't have to manually restore your existing translations.
The script tries to match the existing string files as closely as possible to avoid having too big a diff when updating them.
Naming your strings
If you use NSLocalizedString as advertised:
NSLocalizedString(#"Cancel or continue?", #"Cancel notice message when a download takes too long to proceed");
You may end up defining the same string in another part of your code, which may conflict as the same english term may have different meaning in different contexts (OK and Cancel come to mind).
That is why I always use a meaningless all-caps string with a module-specific prefix, and a very precise description:
NSLocalizedString(#"DOWNLOAD_CANCEL_OR_CONTINUE", #"Cancel notice window title when a download takes too long to proceed");
Using the same string in different places
If you use the same string multiple times, you can either use a macro as you did, or cache it as an instance variable in your view controller or your data source.
This way you won't have to repeat the description which may get stale and get inconsistent among instances of the same localization, which is always confusing.
As instance variables are symbols, you will be able to use auto-completion on these most common translations, and use "manual" strings for the specific ones, which would only occur once anyway.
I hope you'll be more productive with Cocoa localization with these tips!
As for autocompletition for strings in Xcode, you could try https://github.com/questbeat/Lin.
Agree with ndfred, but I would like to add this:
Second parameter can be use as ... default value!!
(NSLocalizedStringWithDefaultValue does not work properly with genstring, that's why I proposed this solution)
Here is my Custom implementation that use NSLocalizedString that use comment as default value:
1 . In your pre compiled header (.pch file) , redefine the 'NSLocalizedString' macro:
// cutom NSLocalizedString that use macro comment as default value
#import "LocalizationHandlerUtil.h"
#undef NSLocalizedString
#define NSLocalizedString(key,_comment) [[LocalizationHandlerUtil singleton] localizedString:key comment:_comment]
2. create a class to implement the localization handler
#import "LocalizationHandlerUtil.h"
#implementation LocalizationHandlerUtil
static LocalizationHandlerUtil * singleton = nil;
+ (LocalizationHandlerUtil *)singleton
{
return singleton;
}
__attribute__((constructor))
static void staticInit_singleton()
{
singleton = [[LocalizationHandlerUtil alloc] init];
}
- (NSString *)localizedString:(NSString *)key comment:(NSString *)comment
{
// default localized string loading
NSString * localizedString = [[NSBundle mainBundle] localizedStringForKey:key value:key table:nil];
// if (value == key) and comment is not nil -> returns comment
if([localizedString isEqualToString:key] && comment !=nil)
return comment;
return localizedString;
}
#end
3. Use it!
Make sure you add a Run script in your App Build Phases so you Localizable.strings file will be updated at each build, i.e., new localized string will be added in your Localized.strings file:
My build phase Script is a shell script:
Shell: /bin/sh
Shell script content: find . -name \*.m | xargs genstrings -o MyClassesFolder
So when you add this new line in your code:
self.title = NSLocalizedString(#"view_settings_title", #"Settings");
Then perform a build, your ./Localizable.scripts file will contain this new line:
/* Settings */
"view_settings_title" = "view_settings_title";
And since key == value for 'view_settings_title', the custom LocalizedStringHandler will returns the comment, i.e. 'Settings"
VoilĂ  :-)
In Swift I'm using the following, e.g. for button "Yes" in this case:
NSLocalizedString("btn_yes", value: "Yes", comment: "Yes button")
Note usage of the value: for the default text value. The first parameter serves as the translation ID. The advantage of using the value: parameter is that the default text can be changed later but the translation ID remains the same. The Localizable.strings file will contain "btn_yes" = "Yes";
If the value: parameter was not used then the first parameter would be used for both: for the translation ID and also for the default text value. The Localizable.strings file would contain "Yes" = "Yes";. This kind of managing localization files seems to be strange. Especially if the translated text is long then the ID is long as well. Whenever any character of the default text value is changed, then the translation ID gets changed as well. This leads to issues when external translation systems are used. Changing of the translation ID is understood as adding new translation text, which may not be always desired.
I wrote a script to help maintaining Localizable.strings in multiple languages. While it doesn't help in autocompletion it helps to merge .strings files using command:
merge_strings.rb ja.lproj/Localizable.strings en.lproj/Localizable.strings
For more info see:
https://github.com/hiroshi/merge_strings
Some of you find it useful I hope.
If anyone looking for a Swift solution. You may want to check out my solution I put together here: SwiftyLocalization
With few steps to setup, you will have a very flexible localization in Google Spreadsheet (comment, custom color, highlight, font, multiple sheets, and more).
In short, steps are: Google Spreadsheet --> CSV files --> Localizable.strings
Moreover, it also generates Localizables.swift, a struct that acts like interfaces to a key retrieval & decoding for you (You have to manually specify a way to decode String from key though).
Why is this great?
You no longer need have a key as a plain string all over the places.
Wrong keys are detected at compile time.
Xcode can do autocomplete.
While there're tools that can autocomplete your localizable key. Reference to a real variable will ensure that it's always a valid key, else it won't compile.
// It's defined as computed static var, so it's up-to-date every time you call.
// You can also have your custom retrieval method there.
button.setTitle(Localizables.login.button_title_login, forState: .Normal)
The project uses Google App Script to convert Sheets --> CSV , and Python script to convert CSV files --> Localizable.strings You can have a quick look at this example sheet to know what's possible.
with iOS 7 & Xcode 5, you should avoid using the 'Localization.strings' method, and use the new 'base localisation' method. There are some tutorials around if you google for 'base localization'
Apple doc : Base localization
#define PBLocalizedString(key, val) \
[[NSBundle mainBundle] localizedStringForKey:(key) value:(val) table:nil]
Myself, I'm often carried away with coding, forgetting to put the entries into .strings files. Thus I have helper scripts to find what do I owe to put back into .strings files and translate.
As I use my own macro over NSLocalizedString, please review and update the script before using as I assumed for simplicity that nil is used as a second param to NSLocalizedString. The part you'd want to change is
NSLocalizedString\(#(".*?")\s*,\s*nil\)
Just replace it with something that matches your macro and NSLocalizedString usage.
Here comes the script, you only need Part 3 indeed. The rest is to see easier where it all comes from:
// Part 1. Get keys from one of the Localizable.strings
perl -ne 'print "$1\n" if /^\s*(".+")\s*=/' myapp/fr.lproj/Localizable.strings
// Part 2. Get keys from the source code
grep -n -h -Eo -r 'NSLocalizedString\(#(".*?")\s*,\s*nil\)' ./ | perl -ne 'print "$1\n" if /NSLocalizedString\(#(".+")\s*,\s*nil\)/'
// Part 3. Get Part 1 and 2 together.
comm -2 -3 <(grep -n -h -Eo -r 'NSLocalizedString\(#(".*?")\s*,\s*nil\)' ./ | perl -ne 'print "$1\n" if /NSLocalizedString\(#(".+")\s*,\s*nil\)/' | sort | uniq) <(perl -ne 'print "$1\n" if /^\s*(".+")\s*=/' myapp/fr.lproj/Localizable.strings | sort) | uniq >> fr-localization-delta.txt
The output file contains keys that were found in the code, but not in the Localizable.strings file. Here is a sample:
"MPH"
"Map Direction"
"Max duration of a detailed recording, hours"
"Moving ..."
"My Track"
"New Trip"
Certainly can be polished more, but thought I'd share.

How Do I Change the File Naming Convention for Scripted Objects Files in SQL2005?

SQL Server 2005 Express Edition SP2 supports scripting of objects into separate files. By default, the filenames include the name of the object's owner, the name of the SQL object followed by the object type. For example, dbo.Employee.Table.sql or dbo.GSP_EmployeeUpdate.StoredProcedure.sql. Though this naming convention may help one to quickly determine what's scripted within a given file, it doesn't help with file organization (i.e. I can't sort by object type.) Therefore, I would like to change the file naming convention. Is this possible?
I don't know if customization like this is possible but what about using little PowerShell like this:
ls | % {rni -path $_.Name -new ($_.name.Split('.')[0] + "." + $_.name.Split('.')[2] + "." +$_.name.Split('.')[1] + "." +$_.name.Split('.')[3])}
Maybe someone can give even better snippet ?