Is there a Go function that works like linux cut? - string

This is probably a very basic question, but I have not been able to find an answer after reviewing the strings package docs.
Basically, all I want to do is the equivalent of:
echo "hello world" | cut -d" " -f2

echo "hello world" | cut -d" " -f2
This splits the string "hello world" using spaces as delimeters, and selects only the 2nd part (1-indexed).
In Go for spitting there is strings.Split() which returns a slice, which you can index or slice however you like.
s := "hello world"
fmt.Println(strings.Split(s, " ")[1])
This outputs the same. Try it on the Go Playground. If the input is not guaranteed to have 2 parts, the above indexing ([1]) might panic. Check the length of the slice before doing so.

There is the strings.Split() function which splits the string at the specified sub-string.
There are also the functions Fields(s string) []string, and FieldsFunc(s string, f func(rune) bool) []string.
The former split the string at spaces, and the later uses the given function to determine if the string must be split.
The difference between Split and Fields is that Fields consider multiple consecutive spaces as one split location. strings.Fields(" foo bar baz ")) yields ["foo" "bar" "baz"], and strings.Split(" foo bar baz ", " ") yields ["" "" "foo" "bar" "" "baz" "" "" ""].

Related

Bash: repeat character a variable number of times

Per the questions and ruminations in:
https://unix.stackexchange.com/questions/188658/writing-a-character-n-times-using-the-printf-command
and
How can I repeat a character in bash?
I would like to learn how one might go about parameterizing the repeat value for a character/string. For example, the followings works spiffingly:
printf " ,\n%0.s" {1..5}
However, if I wanted to parameterize '5', say:
num=5
I cannot seem to get the expansion correct to make this work. For instance:
printf " ,\n%0.s" {1..$((num))}
fails.
Any thoughts/ideas would be most welcome - I reckon there's a way to do this without having to resort to perl or awk so just curious if poss.
Thanks!
You can use seq
num=20;
printf '\n%.0s' $(seq $num)
If you can build the command as a string -- with all the parameter expansion you want -- then you can evaluate it. This prints X num times:
num=10
eval $(echo printf '"X%0.s"' {1..$num})
A slighly different approach
$ repeat() {
local str=$1 n=$2 spaces
printf -v spaces "%*s" $n " " # create a string of spaces $n chars long
printf "%s" "${spaces// /$str}" # substitute each space with the requested string
}
$ repeat '!' 10
!!!!!!!!!! # <= no newline
$ repeat $' ,\n' 5
,
,
,
,
,

Looking for a breakdown of echo{,} foo

How does the expression {,} work?
I tried searching around SOF as well as on google and even the man pages for bash, yet I haven't been able to come across an explanation for this.
From fiddling around with the expression I've learned that it's some sort of string copying function.
echo{,} foo
>> echo echo foo
echo foo{,}
>> foo foo
How does this expression work? Is there a name for this? Also, can you provide a practical example for the use of this function?
It's called brace expansion.
Here's a simple explanation.
{,} will repeat left adjacent string exactly 2 times by appending empty strings.
Similarly {,,} will repeat left adjacent string exactly 3 times.
var{A,B} will return varA and varB
And these examples should clarify more:
echo foo{,,}
foo foo foo
echo foo{,1}
foo foo1
echo foo{1,2}
foo1 foo2
echo foo{,,}
foo foo foo
echo foo{1,2,3}
foo1 foo2 foo3
Link to the docs
The "normal" use case for brace expansion is to repeat a string with a substring replaced by each element of a list given in curly braces:
$ echo file.{txt,dat,log}
file.txt file.dat file.log
Now, if one of the list elements is empty, the string gets printed as is:
$ echo file.{txt,dat,}
file.txt file.dat file.
A popular use case for this is to rename a file
$ mv -v file.txt{,.bak}
'file.txt' -> 'file.txt.bak'
This expands to mv -v file.txt file.txt.bak, because the first list element is empty.
Now, if all elements are empty as in {,}, the string just gets printed as many times as there are list elements.

Reason for the text converting from "ZZ" to "1" when i try to add "ZZ"+1

I just want to know the reason if i use the (.) instead i got the result but + is doing arhtematic addition but how is that ASCII addition
my $string = "ZZ";
my $appendstring = $string+1;
print $appendstring;
output
1
Expeccting
ZZ1
First of all, your question is very unclear, and your "example" (if you want to call it that) does not match reality, but in an effort to help whoever stumbles across this question in the future, I'm going to venture an answer anyway.
Let's clear up your example first:
$ perl -lwe '$x = "ZZ"; print $x + 1;'
Argument "ZZ" isn't numeric in addition (+) at -e line 1.
1
What I think you might have meant was:
$ perl -lwe '$x = "ZZ"; print ++$x;'
AAA
And the reason for that is explained in perlop:
The auto-increment operator has a little extra builtin magic to it. If
you increment a variable that is numeric, or that has ever been used
in a numeric context, you get a normal increment. If, however, the
variable has been used in only string contexts since it was set, and
has a value that is not the empty string and matches the pattern
/^[a-zA-Z]*[0-9]*\z/, the increment is done as a string, preserving
each character within its range, with carry.
Edit: your updated question isn't any clearer than your original question, but now I think you're asking about string concatenation, which means you want the string concatenation operator: .
$ perl -lwe '$x = "ZZ"; print $x . 1;'
ZZ1
There is, however, a special case where you can use a string with the numeric addition operator and not generate a warning:
$ perl -lwe '$x = "0 but true"; print $x + 1;'
1
You also mentioned "ASCII addition", but I have no idea what that is or what you mean by that.
According to this
this is the way to concatenate
use strict;
use warnings;
my $x = "4T";
my $y = 3;
print $x . $y; # 4T3
but if you do this:
print $x + $y; # 7
# Argument "4T" isn't numeric in addition (+) at ...
Whenever you use the "+" perl tries to convert both values to numeric, if you provide a string and a number or 2 strings it'll take these as 0 and sum them.
http://ideone.com/0LyEij

Get the characters after the last index of a substring from a string

I have a string which is an output of another command. I only need the end of this string to display. The separator string is "." (dot and space), and I need the string after the last index of ".".
How can I do this in Bash?
If the string is in a variable:
$ foo="header. stuff. more stuff"
$ echo "${foo##*. }"
more stuff
If there are multiple instances of ". " (as in my example) and you want everything after the first occurrence, instead of the last, just use one #:
$ echo "${foo#*. }"
stuff. more stuff
try this:
your cmd...|sed 's/.*\. //'
this works no matter how many "dot" or "dot and space" do you have in your input. it takes the string after the last "dot and space"
Awk is elegant weapon...for a more civilized age:
[cpetro01#h ~]$ echo "this. is. my. string. of. some. arbitrary. length" | awk -F'. ' ' { print $NF } '
length
[cpetro01#h ~]$ echo "this. is. my. string. of. some" | awk -F'. ' ' { print $NF } '
some
In this case NF is the awk variable for "Number of fields" and this construct says "print the entry in highest number of fields found" so if the size of your input changes from one line to the next you're still going to get the last one.
You can also do math:
[cpetro01#h~]$ echo "this. is. my. string. of. some. arbitrary. length" | awk -F'. ' ' { print $(NF-2) } '
some
[cpetro01#h~]$ echo "this. is. my. string. of. some. arbitrary. length" | awk -F'. ' ' { print $(NF-3) } '
of
[cpetro01#h~]$
(Yes, this is 3 years late for the OP, but one of my cow-orkers pointed me to this page today for something we were working on, so I thought I'd drop this here in case others are looking too.)
Try this:
echo "This is a sentence. This is another sentence" | rev | cut -d "." -f1 | rev
The rev reverses the output. The -d specifies the delimiter, breaking everything up into fields. The -f specifies the fields you want to use. We can select f1, because we reversed the data. We don't need to know how many fields there are in total. We just need to know the first. At the end, we reverse it again, to put it back in the right order.

string alignment in perl / match alignment

I have two strings $dna1 and $dna2. Print the two strings as concatenated, and then print the second string lined up over its copy at the end of the concatenated strings. For example, if the input
strings are AAAA and TTTT, print:
AAAATTTT
TTTT
this is a self exercise question .. not a homework ,
i tried using index
#!/usr/bin/perl -w
$a ='AAAAAAAAAATTTTTTTTT';
$b ='TTTTTTTTTT';
print $a,"\n";
print ''x index($a,$b),$b,"\n";
but it is not working as needed .help please
Start by checking what index($a,$b) is returning... Perhaps you should pick a $b that's actually in $a!
Then realise that concatenating 10 instances of an empty string is an empty string, not 10 spaces.
This is a fun little exercise. I did this:
perl -lwe'$a="AAAA"; $b="TTTT"; $c = $a.$b; $i = index($c,$b) + length($b);
print $c; printf "%${i}s\n", $b;'
AAAAAAATTTT
TTTT
Note that generally speaking, using the variable names $a through $c is a bad idea, and only acceptable here because it is a one-liner. $a and $b are also reserved variable names used with sort.

Resources