I have to implement a feature in which i have a file name and that name contains some integer value in the end and i want to increment that integer value by one. To be more clear, the problem string "filename" is :
asdfasdfasdfa.foo.old001
now i have to check if this file name exists, and if it does i have to name my new file to
asdfasdfasdfa.foo.old002
and so on. I can think of one solution which is to get the last string ".old001" using
file extension string
command and then using regular expression get the last three characters and add '1' to it and then join the file name to this new extension. But i am not sure if it is a good and optimal solution. Any other ideas or help would be great. Thanks.
proc incr_filename {name} {
set digits [regexp -inline {\d+$} $name]
set prefix [string range $name 0 end-[string length $digits]]
set num [scan $digits %d] ;# prevents problems with invalid octal numbers
format "%s%0*d" $prefix [string length $digits] [incr num]
}
puts [incr_filename asdfasdfasdfa.foo.old001]
And to find the non-existant filename:
set filename abcd.ext.old001
while {[file exists $filename]} {
set filename [incr_filename $filename]
}
puts "new filename is $filename"
Related
Given a string, I'd like to know if the string represents a valid file path. I've looked at [file isfile <string>] and [file isdirectory <string>] but it seems those two return false if the given string isn't pointing to an existing file/directory. I'm merely interested in the validity of the string.
Pretty much every string is a valid file path. Can you give some examples of what you consider invalid file paths?
You can use file pathtype to check if the path is absolute. Also file split and file normalize may be useful, depending on what you really need.
I don't know that there's a particular way to do that.
I suppose you could try:
set fn /home/bll/mytest.txt
set fail true
if { [file exists $fn] } {
set fail false
} else {
try {
set fh [open $fn w]
set fail false
file delete $fn
} on error {err res} {
}
}
Even if the above works, certain characters may cause issues if you use
the filename in an external command line.
I strip the following characters simply to avoid possible command line problems:
* : " ? < > | [:cntrl:]
I have this list as possibly problematical for unix:
* & [] ? ' " < > |
And this list for windows:
* : () & ^ | < > ' "
Also, a trailing dot is illegal for windows directory names.
And slashes or backslashes can cause issues as those are directory separators.
I have a file file.dat as follow:
1.1,2.1 1.4
3.1,2.1 2.4
2.4,4.5 11.5
..
And I want to select each time the whole line (string) and replace it in another file. So far I tried the following
#!/bin/csh
set FILENAME = 'file.dat' # file in which the strings are
set str = "229.8,230.9 230.36" # initialize the first string
set n = 1
while ( $n <= 3 ) # number of lines in the FILENAME
echo Testing the first string $str
set rep = $(head -n $n "$FILENAME")
# n++ # increment the index
end
When I tried to launch the script csh launch.sh I obtained the follow error message
Testing the first string 229.8,230.9 230.36
Illegal variable name. # connect with the rep definition(?)
The file in which I want to change the string str is as follow (this is btw a secondary problem which I could figure out by myself once I understand what's wrong in the first lines):
# Name Type Par
Mi FI 154.2355189465
So UN 229.8,230.9 230.36 # line to be changed
Za FI 0.8000020209
May somebody help me, please?
$(...) is Bash syntax for command substitution in Bash.
In C-shell you have to use backticks instead (yuck).
I'm working with DNA sequences in a file, and this file is formatted something like this, though with more than one sequence:
>name of sequence
EXAMPLESEQUENCEATCGATCGATCG
I need to be able to tell if a variable (which is also a sequence) matches any of the sequences in the file, and what the name of the sequence it matches, if any, is. Because of the nature of these sequences, my entire variable could be contained in a line of the file, or a line of the variable could be a part of my variable.
Right now my code looks something like this:
use warnings;
use strict;
my $filename = "/users/me/file/path/file.txt";
my $exampleentry = "ATCG";
my $returnval = "The sequence does not match any in the file";
open file, "<$filename" or die "Can't find file";
my #Name;
my #Sequence;
my $inx = 0;
while (<file>){
$Name[$inx] = <file>;
$Sequence[$inx] = <file>;
$indx++;
}unless(index($Sequence[$inx], $exampleentry) != -1 || index($exampleentry, $Sequence[$inx]) != -1){
$returnval = "The sequence matches: ". $Name[$inx];
}
print $returnval;
However, even when I purposely set $entry as a match from the file, I still return The sequence does not match any in the file. Also, when running the code, I get Use of uninitialized value in index at thiscode.pl line 14, <file> line 3002. as well as Use of uninitialized value within #Name in concatenation (.) or string at thiscode.pl line 15, <file> line 3002.
How can I perform this search?
I will assume that the purpose of this script is to determine if $exampleentry matches any record in the file file.txt. A record describes here a DNA sequence and corresponds to three consecutive lines in the file. The variable $exampleentry will match the sequence if it matches the third line of the record. A match means here that either
$exampleentry is a substring of $line, or
$line is a substring of $exampleentry,
where $line referes to the corresponding line in the file.
First, consider the input file file.txt:
>name of sequence
EXAMPLESEQUENCEATCGATCGATCG
in the program you try to read these two lines, using three calls to readline. Accordingly, that last call to readline will return undef since there are no more lines to read.
It therefore seems reasonable that the two last lines in file.txt are malformed, and the correct format should be:
>name of sequence
EXAMPLESEQUENCE
ATCGATCGATCG
If I now understand you correctly, I hope this could solve your problem:
use feature qw(say);
use strict;
use warnings;
my $filename = "file.txt";
my $exampleentry = "ATCG";
my $returnval = "The sequence does not match any in the file";
open (my $fh, '<', $filename ) or die "Can't find file: $!";
my #name;
my #sequence;
my $inx = 0;
while (<$fh>) {
chomp ($name[$inx] = <$fh>);
chomp ($sequence[$inx] = <$fh>);
if (
index($sequence[$inx], $exampleentry) != -1
|| index($exampleentry, $sequence[$inx]) != -1
) {
$returnval = "The sequence matches: ". $name[$inx];
last;
}
}
say $returnval;
Notes:
I have changed variable names to follow snake_case convention. For example the variable #Name is better written using all lower case as #name.
I changed the open() call to follow the new recommended 3-parameter style, see Don't Open Files in the old way for more information.
Used feature say instead of print
Added a chomp after each readline to avoid storing newline characters in the arrays.
I have a snippet of code that I use for a program that I have [Thus some of the app specific code] ...Anyway I am trying to capitalize the first letter of each word unless the word is in caps.
for example: >>this is text THAT would be CHANGED.
The code that i have thus far is as follows.
Again some of this is app specific I am not able to use "puts," the result has to be returned as return "" this is the reason that I create a var and add to it word by word.
proc ToTitle {} {
set Input [sh_set clipboard]
set CleanedInput [string map {" " |} [string trimright [string trimleft $Input]]]
set InputList [split $CleanedInput "|"]
set wresult ""
set item 0
foreach line $InputList {
set List_Item [lindex $InputList $item];
if {[string is upper $List_Item] == 1} {
set newline $List_Item
set wresult "$wresult $newline"
incr item
} else {
set newline [string totitle $List_Item]
set wresult "$wresult $newline"
incr item
}
}
regsub -all {\u0020{2,}} $wresult " " wresult; #REMOVE ALL EXCESSIVE SPACE CHARACTERS
set $wresult [string trimright [string trimleft $wresult]]; # TRIM ALL OF THE WHITESPACE BEFORE AND AFTER THE STRING
return "$wresult"}
This is currently working the output would be:
This Is Text THAT Would Be Changed.
The issue is the "Changed." because of the "."
The question is What can I use to only read the word character on items that have special characters or word characters?
{[string is upper $List_Item] == 1}
I know there is something that I can add to that to check it...
Thankyou in advance for all the help.
I think there's a simpler solution. Try this:
set a "this is text THAT would be CHANGED."
set out ""
foreach word $a {
append out "[string toupper $word 0 0] "
}
puts $out
Running it gives this output:
% % % This Is Text THAT Would Be CHANGED.
I have a variable that is entered at a prompt:
my $name = <>;
I want to append a fixed string '_one'to this (in a separate variable).
E.g. if $name = Smith then it becomes 'Smith_one'
I have tried several various ways which do not give me the right results, such as:
my $one = "${name}_one";
^ The _one appears on the next line when I print it out and when I use it, the _one is not included at all.
Also:
my $one = $name."_one";
^ The '_one' appears at the beginning of the string.
And:
my $end = '_one';
my $one = $name.$end;
or
my $one = "$name$end";
None of these produce the result I want, so I must be missing something related to how the input is formatted from the prompt, perhaps. Ideas appreciated!
Your problem is unrelated to string appending: When you read a line (e.g. via <>), then the record input separator is included in that string; this is usually a newline \n. To remove the newline, chomp the variable:
my $name = <STDIN>; # better use explicit filehandle unless you know what you are doing
# now $name eq "Smith\n"
chomp $name;
# now $name eq "Smith"
To interpolate a variable into a string, you usually don't need the ${name} syntax you used. These lines will all append _one to your string and create a new string:
"${name}_one" # what you used
"$name\_one" # _ must be escaped, else the variable $name_one would be interpolated
$name . "_one"
sprintf "%s_one", $name
# etc.
And this will append _one to your string and still store it in $name:
$name .= "_one"