I am trying to understand the :t in following code but could not figure out and these piece of code need to convert in tcl. When We print it split the word the on the slash and it return the last element. ex: user3,user,etc
suppose d = /home/etc/user/user3
while 1 {
set _f $_d:t
}
You're probably looking for file tail:
set _f [file tail $_d]
It's not normally good style to start a Tcl variable name with _, but it's quite legal to do so if you want to.
Related
I am working on a Automator service and in my situation I have stdin as
B-Funny Flash Nonfiction 202105131635 and I want to get to B-Funny Flash Nonfiction 202105131636 incriminating the "5" by 1 to "6".
I'd think I'd first want to separate the text from the number before doing the add 1 then rejoin them?
Would egrep or sed or awk be best?
Tips?
Bash has simple integer arithmetic built in.
str='B-Funny Flash Nonfiction 202105131635'
# parse into prefix and number
num=${str##*[!0-9]}
prefix=${str%$num}
echo "$prefix$((num+1))"
The parameter expansion ${var#pat} produces the value of the variable var with any prefix matching pat removed; % does the same for suffixes, and doubling the operator changes to matching the longest possible pattern match instead of the shortest. The pattern *[!0-9] matches a string which ends on a character which isn't a number; in this context, it retrieves the prefix, i.e. everything up to just before the first digit. (If your prefix could contain numbers, too, this needs tweaking. Probably switch to removing all digits from the end, then extracting the removed numbers; but I guess this will require an unattractive temporary variable.)
Finally, the secret sauce which evaluates an arithmetic expression is the $((...)) arithmetic context.
For more involved number crunching, try bc or Awk. In fact, this could be a one-liner in Awk:
awk '{ $NF +=1 }1' <<<"$str"
The here string passes the value as standard input to Awk, which increments the last field $NF. The final 1 is a common Awk shorthand for "print all input lines to output".
I don't know the bash tools well enough to give a cool one-line answer, so here is a python script instead.
Usage
Save the code in a file increment.py;
Make the file executable with chmod +x increment.py;
Run the script with ./increment.py blablabla 123.
Code
#!/usr/bin/env python3
import sys
def print_help(argv0):
print('increment numbers by 1')
print('example usage:')
print(' {} B-Funny Flash Nonfiction 202105131635'.format(argv0))
print(' B-Funny Flash Nonfiction 202105131636')
def main(argv):
if len(argv) < 2:
print_help(argv[0])
else:
for s in argv[1:]:
if s.isnumeric():
print(int(s) + 1, end=' ')
else:
print(s, end=' ')
print()
if __name__=='__main__':
main(sys.argv)
Explanation
In a python program called from the command-line, the command-line arguments are stored in the array sys.argv.
The first element of the array, with index 0, is the name that was used to call the program, most likely "./increment.py" in our case.
The remaining elements are the parameters that were passed to the program; the words "B-Funny", "Flash", "Nonfiction", "202105131635" in our case.
The for-loop for s in argv[1:]: iterates on the elements of argv, but starting with the element 1 (thus ignoring the element 0). Each of these elements is a string; the method .isnumeric is used to check whether this string represents a number or not. Refer to the documentation on .isnumeric.
If the string is not numeric, we print is as-is. If the string is numeric, we compute the number it represents by calling int(s), then we add 1, and we print the result.
Apart from that, the line if len(argv): checks whether argv contains at least two elements; if it doesn't, that means it only contains its element 0, which is "./increment.py"; in this case, instead of printing the arguments, the script calls the function print_help which explains how to use the program.
Finally, the bit about if __name__ == '__main__': is a python idiom to check whether the file increment.py was run as a program or as a module imported by another file. Refer to this question.
How can I access command line arguments in Nim?
The documentation shows only how to run the compiled Nim code with command line arguments
nim compile --run greetings.nim arg1 arg2
but I didn't find how to use their values in code.
Here's an example that prints the number of arguments and the first argument:
import os
echo paramCount(), " ", paramStr(1)
Personally I find paramCount and paramStr a bit confusing to work with, because the paramCount value differs from C conventions (see the document links).
Fortunately, there are additional convenient functions which do not require to be aware of the conventions:
commandLineParams returns a seq of only command line params.
getAppFilename returns the executable file name (what is argv[0] in the C world).
I have not checked when it was added, but the parseopt seems to me, the default and the best way for this.
commandLineParams isn't available on Posix.
os.commandLineParams() returns a sequence of command-line arguments provided to the program.
os.quoteShellCommand(<openArray[string]>) takes a sequence of command-line arguments and turns it into a single string with quotes around items containing spaces, so the string can be parsed properly.
parseopt.initOptParser(<string>) takes a full command-line string and parses it, returning an OptParser object.
parseopt.getopt(<OptParser>) is an iterator that yields parsed argument info.
You can combine them to parse a program's input arguments:
import std/[os, parseopt]
proc writeHelp() = discard
proc writeVersion() = discard
var positionalArgs = newSeq[string]()
var directories = newSeq[string]()
var optparser = initOptParser(quoteShellCommand(commandLineParams()))
for kind, key, val in optparser.getopt():
case kind
of cmdArgument:
positionalArgs.add(key)
of cmdLongOption, cmdShortOption:
case key
of "help", "h": writeHelp()
of "version", "v": writeVersion()
of "dir", "d":
directories.add(val)
of cmdEnd: assert(false) # cannot happen
echo "positionalArgs: ", positionalArgs
echo "directories: ", directories
Running this with nim c -r main.nim -d:foo --dir:bar dir1 dir2 dir3 prints:
positionalArgs: #["dir1", "dir2", "dir3"]
directories: #["foo", "bar"]
I have a list of file paths, for example
[
'Useful',
'../Some.Root.Directory/Path/Interesting',
'../Some.Root.Directory/Path/Also/Interesting'
]
(I mention that they're file paths in case there is something that makes this task easier because they're files but they can be considered simply a set of strings some of which may start with a particular string)
and I need to make this into a set of pairs so that I have the original list but also
[
'Useful',
'Interesting',
'Also/Interesting'
]
I expected I'd be able to do this
'../Some.Root.Directory/Path/Interesting'.gsub!('../Some.Root.Directory/Path/', '')
or
'../Some.Root.Directory/Path/Interesting'.gsub!('\.\.\/Some\.Root\.Directory\/Path\/', '')
but neither of those replaces the provided string/pattern with an empty string...
So in irb
puts '../Some.Root.Directory/Path/Interesting'.gsub('\.\.\/Some\.Root\.Directory\/Path\/', '')
outputs
../Some.Root.Directory/Path/Interesting
and the desired output is
Interesting
How can I do this?
NB the path will be passed in so really I have
file_path.gsub!(removal_path, '')
If you are positive that strings start with removal_path you can do:
string[removal_path.size..-1]
to get the remaining part.
If you want to get pairs of the original paths and the shortened ones, you can use sub in combination with map:
a = [
'../Some.Root.Directory/Path/Interesting',
'../Some.Root.Directory/Path/Also/Interesting'
]
b = a.map do |v|
[v, v.sub('../Some.Root.Directory/Path', '')]
end
puts b
This will return an Array of arrays - each sub-array contains the original path plus the shortened one. As noted by #sawa - you can simply use sub instead of gsub, since you want to replace only a single occurrence.
I have a file with one or more key:value lines, and I want to pull a key:value out if key=foo. How can I do this?
I can get as far as this:
if File.exist?('/file_name')
content = open('/file_name').grep(/foo:??/)
I am unsure about the grep portion, and also once I get the content, how do I extract the value?
People like to slurp the files into memory, which, if the file will always be small, is a reasonable solution. However, slurping isn't scalable, and the practice can lead to excessive CPU and I/O waits as content is read.
Instead, because you could have multiple hits in a file, and you're comparing the content line-by-line, read it line-by-line. Line I/O is very fast and avoids the scalability problems. Ruby's File.foreach is the way to go:
File.foreach('path/to/file') do |li|
puts $1 if li[/foo:\s*(\w+)/]
end
Because there are no samples of actual key/value pairs, we're shooting in the dark for valid regex patterns, but this is the basis for how I'd solve the problem.
Try this:
IO.readlines('key_values.txt').find_all{|line| line.match('key1')}
i would recommend to read the file into array and select only lines you need:
regex = /\A\s?key\s?:/
results = File.readlines('file').inject([]) do |f,l|
l =~ regex ? f << "key = %s" % l.sub(regex, '') : f
end
this will detect lines starting with key: and adding them to results like key = value,
where value is the portion going after key:
so if you have a file like this:
key:1
foo
key:2
bar
key:3
you'll get results like this:
key = 1
key = 2
key = 3
makes sense?
value = File.open('/file_name').read.match("key:(.*)").captures[0] rescue nil
File.read('file_name')[/foo: (.*)/, 1]
#=> XXXX
So I have the following little script to make a file setup for organizing reports that we get.
#This script is to create a file structure for our survey data
require 'fileutils'
f = File.open('CustomerList.txt') or die "Unable to open file..."
a = f.readlines
x = 0
while a[x] != nil
Customer = a[x]
FileUtils.mkdir_p(Customer + "/foo/bar/orders")
FileUtils.mkdir_p(Customer + "/foo/bar/employees")
FileUtils.mkdir_p(Customer + "/foo/bar/comments")
x += 1
end
Everything seems to work before the while, but I keep getting:
'mkdir': Invalid argument - Cust001_JohnJacobSmith(JJS) (Errno::EINVAL)
Which would be the first line from the CustomerList.txt. Do I need to do something to the array entry to be considered a string? Am I mismatching variable types or something?
Thanks in advance.
The following worked for me:
IO.foreach('CustomerList.txt') do |customer|
customer.chomp!
["orders", "employees", "comments"].each do |dir|
FileUtils.mkdir_p("#{customer}/foo/bar/#{dir}")
end
end
with data like so:
$ cat CustomerList.txt
Cust001_JohnJacobSmith(JJS)
Cust003_JohnJacobSmith(JJS)
Cust002_JohnJacobSmith(JJS)
A few things to make it more like the ruby way:
Use blocks when opening a file or iterating through arrays, that way you don't need to worry about closing the file or accessing the array directly.
As noted by #inger, local vars start with lower case, customer.
When you want the value of a variable in a string usign #{} is more rubinic than concatenating with +.
Also note that we took off the trailing newline using chomp! (which changes the var in place, noted by the trailing ! on the method name)