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.
Related
I want to compare two strings in TCL and replace the unmatched character with asterisk.
Core_cpuss_5/loop2/hex_reg[89]cpu_ip[45]_reg10/D[23]
Core_cpuss_5/loop2/hex_reg[56]cpu_ip[12]_reg5/D[33]
Output Required : Core_cpuss_5/loop2/hex_reg[ * ]cpu_ip[ * ]_reg*/D[*]
I tried above using regsub but not working as expected.
foreach v {string1 string2} {
regsub {\[[0-9]+\]$} $v {[*]} v_modified
}
To replace the integers inside the square brackets with * (and also change reg10 and reg5 to reg*)
set string1 {Core_cpuss_5/loop2/hex_reg[89]cpu_ip[45]_reg10/D[23]}
set string2 {Core_cpuss_5/loop2/hex_reg[56]cpu_ip[12]_reg5/D[33]}
foreach v "$string1 $string2" {
regsub -all {\[\d+\]} $v {[*]} v_modified
regsub -all {reg\d+} $v_modified {reg*} v_modified
puts $v_modified
}
You had a couple problems in your code which I fixed:
Change {string1 string2} to "$string1 $string2"
Add -all to the regexp command find all matches.
Remove the $ from the regular expression because that only matches the final one.
Add another regsub to change reg10 and reg5 to reg*.
If you need a more general purpose solution, this will find a sequence of integers in each string and replace with a * if they are different:
set string1 {Core_cpuss_5/loop2/hex_reg[89]cpu_ip[45]_reg10/D[23]}
set string2 {Core_cpuss_5/loop2/hex_reg[56]cpu_ip[12]_reg5/D[33]}
# Initialize start positions for regexp for each string.
set start1 0
set start2 0
# Incrementally search for integers in each string.
while {1} {
# Find a match for an integer in each string and save the {begin end} indices of the match
set matched1 [regexp -start $start1 -indices {\d+} $string1 indices1]
set matched2 [regexp -start $start2 -indices {\d+} $string2 indices2]
if {$matched1 && $matched2} {
# Use the indices to get the matched integer
set value1 [string range $string1 {*}$indices1]
set value2 [string range $string2 {*}$indices2]
# Replace the integer with *
if {$value1 ne $value2} {
set string1 [string replace $string1 {*}$indices1 "*"]
set string2 [string replace $string2 {*}$indices2 "*"]
}
} else {
break
}
# Increment the start of the next iteration.
set start1 [expr {[lindex $indices1 1]+1}]
set start2 [expr {[lindex $indices2 1]+1}]
}
puts "String1 : $string1"
puts "String2 : $string2"
The above will only work if the two strings are similar enough (like they each have the same number of integers in a similar order)
I'm attempting to use Perl's gethostnamebyaddr function. The annoying thing is that it returns the entire domain name in scalar format. I want to parse out only the hostname and discard the rest.
I'm using split to divide the domain name into an array and then taking only the first value but this doesn't seem to work.
#!/usr/bin/perl
use Socket;
my $name;
my $hostname;
my #tmpStr;
$name = gethostbyaddr(inet_aton("192.168.2.3"), AF_INET);
print "$name\n";
#tmpStr = split ".", $name;
$hostname = $tmpStr[0];
print "Host name is $hostname\n";
When the above code is executed, I get the following:
dc1-ent.ent.ped.local
Host name is
According to this website the return value is not a string but is rather a scalar value and so my attempt at splitting it doesn't work.
I can't figure out how to convert it to a string before I can split it or parse out the hostname by itself.
The dot character has special meaning for regular expressions in Perl, and the 1st argument to split is a regular expression. You need to escape the dot:
use warnings;
use strict;
my $name = 'dc1-ent.ent.ped.local';
print "$name\n";
my #tmpStr = split /\./, $name;
my $hostname = $tmpStr[0];
print "Host name is $hostname\n";
This outputs:
dc1-ent.ent.ped.local
Host name is dc1-ent
I would write it like this
my $name = gethostbyaddr(inet_aton('192.168.2.3'), AF_INET);
my ($host) = $name =~ /([^.]+)/;
say $host;
Your problem is not related to gethostbyaddr() but by what follows.
Proof:
DB<1> $name = 'dc1-ent.ent.ped.local';
DB<2> #tmpStr = split ".", $name;
DB<3> print #tmpStr;
(nothing printed)
Try instead using split that way:
DB<8> $name = 'dc1-ent.ent.ped.local';
DB<9> #tmpStr = split(/\./, $name);
DB<10> print #tmpStr;
dc1-ententpedlocal
DB<11> print join(' ', #tmpStr);
dc1-ent ent ped local
DB<12> x #tmpStr;
0 'dc1-ent'
1 'ent'
2 'ped'
3 'local'
Or if you absolutely want a string and not a regex, protect the dot also as your string is still parsed as a regular expression (which is why being explicit with / / has its merits, it forces you to remember that some character have special meaning there, like the dot):
DB<1> $name = 'dc1-ent.ent.ped.local';
DB<2> #tmpStr = split('.', $name);
DB<3> print #tmpStr;
DB<4> #tmpStr = split('\.', $name);
DB<5> x #tmpStr
0 'dc1-ent'
1 'ent'
2 'ped'
3 'local'
lets say I open a file, then parsed it into lines. Then I use a loop:
foreach line $lines {}
e.g., if the file contained the following string:
XYDATA, NAME1
I want to put ACC_ after the XYDATA to get ACC_NAME1
and if the file contains more than one strings with XYDATA, put VEL_, DSP_ and Prs_ and so on
Using the textutil::split package from tcllib, and the ability of foreach to iterate over multiple lists simultaneously
package require textutil::split
set line {XYDATA, foo, bar, baz, qux}
set prefixes {ACC_ VEL_ DSP_ Prs_}
set fields [textutil::split::splitx $line {, }]
set new [list]
if {[lindex $fields 0] eq "XYDATA"} {
lappend new [lindex $fields 0]
foreach prefix $prefixes field [lrange $fields 1 end] {
lappend new $prefix$field
}
}
puts [join $new ", "]
XYDATA, ACC_foo, VEL_bar, DSP_baz, Prs_qux
alternately, use a single regsub call that generates some code
set code [regsub -all {(, )([^,]+)} $line {\1[lindex $prefixes [incr counter]]\2}]
set counter -1
puts [subst $code]
Using perl, is there any single command which give me the number of lines inside a string?
my $linenum= .... $str ....
It should work for when the string is empty, single line, and multiple lines.
You can count number of newline chars \n in the string (or \r for Mac newline)
my $linenum = $str =~ tr/\n//;
I've adapted #rplantiko's answer into a full subroutine that works the way I picture it, with handling for undef and "". It also knows about how the last line of text can be missing a "\n" and returns the apparent line count ( which is the count of "\n" +1 )
# should work on windows + unix but not the old mac
sub count_lines_in_string {
$_ = shift;
return 0 if( !defined $_ or $_ eq "");
my $lastchar = substr $_, -1,1;
my $numlines = () = /\n/g;
# was last line a whole line with a "\n"?;
return $numlines + ($lastchar ne "\n");
}
say count_lines_in_string("asdf\nasdf\n") ;
say count_lines_in_string undef;
say count_lines_in_string "a";
Try to use a regular expression
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"