<a href="https://genius.com/Run-the-jewels-lie-cheat-steal-lyrics" class=" song_link" title="Lie, Cheat, Steal by Run the Jewels">
I'm trying to extract the link that's in between href="", and set it to a string. Is there any way to do that?
The data in it will change consistantly, it's not always gonna be the same domain. Thanks in advance.
Quick and easy: find the text between href=" and the next " (as " will never appear in the value):
Int32 startIdx = input.IndexOf( "href=\"" );
if( startIdx < 0 ) return null;
Int32 endIdx = input.IndexOf( "\"", startIdx );
if( endIdx < 0 ) return null;
return input.Substring( startIdx, endIdx - startIdx );
I am sure you can find this elsewhere on Stack, but I would use string.split(). You can set up something similar to this...
public static void Main(){
char[] delimiterChars = { '"', ' ' };
string text = "<a href=\"https://genius.com/Run-the-jewels-lie-cheat-steal-lyrics\" class=\" song_link\" title=\"Lie, Cheat, Steal by Run the Jewels\">";
string[] words = text.Split(delimiterChars);
}
Assuming your tag is always structured the same, you will just need to grab the third string in the array to pull out the value you are looking for. You can also search for the index of href, and then split the string based on that, but this is how I would go about it.
Related
I have a string
(ProductAttributes,MapType(StringType,StructType(
List( (CurrentValue,StringType,true), (OldValue,StringType,true),
(LastValue,StringType,true))),true),true)
I need to extract StructType(List( (CurrentValue,StringType,true), (OldValue,StringType,true), (LastValue,Stringy )
I've used string.split using separator as "," but I'm not getting the entire struct string.The string I got while using ","
(ProductAttributes
MapType(StringType
StructType(List( (CurrentValue
StringType
true)
(OldValue
StringType
true)
(LastValue
StringType
true)))
true)
true)
I can give the count parameter as '3' but my string might change.I tried giving separator as '()' the got the full string .
The expected result is something like this.I can build this string using an object but extracting the values from the string is a blocker for me now
{"FieldId":"401","Name":"CurrentValue","Type":"string","ParentName":"ProductAttributes>CurrentValue","ParentId":"4"}
Another string example would be:
(BusinessRules,ArrayType(StructType(List( (Id,IntegerType,true), (ErrorCode,IntegerType,true), (Overrides,ArrayType(StructType(List( (OverrideSource,IntegerType,true), (IsOverridden,BooleanType,true), (ReasonId,IntegerType,true), (OverriddenBy,StringType,true), (OverrideDate,LongType,true), (DependencyProductAttributeIds,ArrayType(IntegerType,true),true))),true),true))),true),true)
As stated in the comments it is hard to know how your string might change in the future, but this answer could be used as a starting point (as it will work with the string you have already provided)
You can find the first instance of StructType and then count the number of ( between the start of the string and the found instance. Then count the same number of ) from the end of the string to get your substring.
var stringToParse = #" (ProductAttributes,MapType(StringType,StructType(
List( (CurrentValue,StringType,true), (OldValue,StringType,true),
(LastValue,StringType,true))),true),true)";
var start = stringToParse.IndexOf("StructType(");
var count = stringToParse.Substring(0, start).Count(c => c == '(');
var end = stringToParse.Length;
for(int i = 0; i < count + 1; i++)
{
end = stringToParse.LastIndexOf(')', end - 1);
}
var result = stringToParse.Substring(start, end - start);
Console.WriteLine(result);
Note: We add 1 to the ( count in the for loop to ensure we count back to the matching ) for our initial search string StructType(
How can i find an operator in the string? After that, I'd like to create get the left and the right variable.
If the string was:
DisengagementPoint=TravelForce
or
DisengagementPoint=100
but some time string be longer like:
DisengagementPoint=100 (VehicleSpeed>2) || (EngineRpm== 0)
And I want to create a string with whatever is on the left side of "=" and one string with right side, how could I do that?
Output that I expected:
var1 = DisengagementPoint
var2 = 100 or TravelForce
var3 = (VehicleSpeed>2) || (EngineRpm== 0)
Sorry this is pretty pseudo, but hopefully it makes sense.
I would like add two things to other excelent answers:
A) The string.Split splits the string by all equals thus DisengagementPoint=100 would go out just fine but line = "DisengagementPoint=100 (VehicleSpeed>2) || (EngineRpm== 0)" would get quite messy since just splitting with string string[] split = line.Split('=') would yield array:
split[0] = "DisengagementPoint"
split[1] = "100 (VehicleSpeed>2) || (EngineRpm"
split[2] = ""
split[3] = " 0)"
This can be eliminated by restricting maximal number of splits with line.Split('=', 2) returns maximally two sub-strings. And also line.Split('=', StringSplitOptions.RemoveEmptyEntries) could help to get rid if empty parts, but this would not be an issue in this case.
B) What with problem of comparison operator ==? Perheaps check if there are only a single equals or more of them and if more, if there are at least two of them right behind themselves.
As mentioned in comment to #Dmitry Bychenko´s post by #AustinWBryan this starts to look parser problem, which is a bit different question in my opinion.
Just find = position and take substrings:
String source = "DisengagementPoint=100";
int index = source.IndexOf('=');
// you may want to test if there's '=' in the string
// if (index >= 0) ...
String left = source.Substring(0, index);
String right = source.Substring(index + 1);
var word = "DisengagementPoint=TravelForce";
var index = word.IndexOf("=");
if(index > 1)
{
var left = word.Substring(0, index);
var right = word.Substring(index + 1,word.Length - index - 1);
}
As DmitryBychenko mentioned
var right = word.Substring(index + 1,word.Length - index - 1);
can be replaced with
var right = word.Substring(index + 1);
I have the following main string which contains link Name and link URL. The name and url is combined with #;. I want to get the string of each link (name and url i.e. My web#?http://www.google.com), see example below
string teststring = "My web#;http://www.google.com My Web2#;http://www.bing.se Handbooks#;http://www.books.se/";
and I want to get three different strings using any string function:
My web#?http://www.google.com
My Web2#?http://www.bing.se
Handbooks#?http://www.books.de
So this looks like you want to split on the space after a #;, instead of splitting at #; itself. C# provides arbitrary length lookbehinds, which makes that quite easy. In fact, you should probably do the replacement of #; with #? first:
string teststring = "My web#;http://www.google.com My Web2#;http://www.bing.se Handbooks#;http://www.books.se/";
teststring = Regex.Replace(teststring, #"#;", "#?");
string[] substrings = Regex.Split(teststring, #"(?<=#\?\S*)\s+");
That's it:
foreach(var s in substrings)
Console.WriteLine(s);
Output:
My web#?http://www.google.com
My Web2#?http://www.bing.se
Handbooks#?http://www.books.se/
If you are worried that your input might already contain other #? that you don't want to split on, you can of course do the splitting first (using #; in the pattern) and then loop over substrings and do the replacement call inside the loop.
If these are constant strings, you can just use String.Substring. This will require you to count letters, which is a nuisance, in order to provide the right parameters, but it will work.
string string1 = teststring.Substring(0, 26).Replace(";","?");
If they aren't, things get complicated. You could almost do a split with " " as the delimiter, except that your site name has a space. Do any of the substrings in your data have constant features, such as domain endings (i.e. first .com, then .de, etc.) or something like that?
If you have any control on the input format, you may want to change it to be easy to parse, for example by using another separator between items, other than space.
If this format can't be changed, why not just implement the split in code? It's not as short as using a RegEx, but it might be actually easier for a reader to understand since the logic is straight forward.
This will almost definitely will be faster and cheaper in terms of memory usage.
An example for code that solves this would be:
static void Main(string[] args)
{
var testString = "My web#;http://www.google.com My Web2#;http://www.bing.se Handbooks#;http://www.books.se/";
foreach(var x in SplitAndFormatUrls(testString))
{
Console.WriteLine(x);
}
}
private static IEnumerable<string> SplitAndFormatUrls(string input)
{
var length = input.Length;
var last = 0;
var seenSeparator = false;
var previousChar = ' ';
for (var index = 0; index < length; index++)
{
var currentChar = input[index];
if ((currentChar == ' ' || index == length - 1) && seenSeparator)
{
var currentUrl = input.Substring(last, index - last);
yield return currentUrl.Replace("#;", "#?");
last = index + 1;
seenSeparator = false;
previousChar = ' ';
continue;
}
if (currentChar == ';' && previousChar == '#')
{
seenSeparator = true;
}
previousChar = currentChar;
}
}
I'm having a problem getting streams for embedded resources. Most online samples show paths that can be directly translated by changing the slash of a path to a dot for the source (MyFolder/MyFile.ext becomes MyNamespace.MyFolder.MyFile.ext). However when a folder has a dot in the name and when special characters are used, manually getting the resource name does not work. I'm trying to find a function that can convert a path to a resource name as Visual Studio renames them when compiling..
These names from the solution ...
Content/jQuery.UI-1.8.2/jQuery.UI.css
Scripts/jQuery-1.5.2/jQuery.js
Scripts/jQuery.jPlayer-2.0.0/jQuery.jPlayer.js
Scripts/jQuery.UI-1.8.2/jQuery.UI.js
... are changed into these names in the resources ...
Content.jQuery.UI_1._8._2.jQuery.UI.css
Scripts.jQuery_1._5._2.jQuery.js
Scripts.jQuery.jPlayer_2._0._0.jQuery.jPlayer.js
Scripts.jQuery.UI_1._8._12.jQuery.UI.js
Slashes are translated to dots. However, when a dot is used in a folder name, the first dot is apparently considered an extension and the rest of the dots are changed to be prefixed with an underscore. This logic does not apply on the jQuery.js file, though, maybe because the 'extension' is a single number? Here's a function able to translate the issues I've had so far, but doesn't work on the jQuery.js path.
protected String _GetResourceName( String[] zSegments )
{
String zResource = String.Empty;
for ( int i = 0; i < zSegments.Length; i++ )
{
if ( i != ( zSegments.Length - 1 ))
{
int iPos = zSegments[i].IndexOf( '.' );
if ( iPos != -1 )
{
zSegments[i] = zSegments[i].Substring( 0, iPos + 1 )
+ zSegments[i].Substring( iPos + 1 ).Replace( ".", "._" );
}
}
zResource += zSegments[i].Replace( '/', '.' ).Replace( '-', '_' );
}
return String.Concat( _zAssemblyName, zResource );
}
Is there a function that can change the names for me? What is it? Or where can I find all the rules so I can write my own function? Thanks for any assistance you may be able to provide.
This is kinda a very late answer... But since this was the first hit on google, I'll post what I've found!
You can simply force compiler to name the embedded resource as you want it; Which will kinda solves this problem from the beginning... You've just got to edit your csproj file, which you normally do if you want wildcards in it! here is what I did:
<EmbeddedResource Include="$(SolutionDir)\somefolder\**">
<Link>somefolder\%(RecursiveDir)%(Filename)%(Extension)</Link>
<LogicalName>somefolder:\%(RecursiveDir)%(Filename)%(Extension)</LogicalName>
</EmbeddedResource>
In this case, I'm telling Visual studio, that I want all the files in "some folder" to be imported as embedded resources. Also I want them to be shown under "some folder", in VS solution explorer (this is link tag). And finally, when compiling them, I want them to be named exactly with same name and address they had on my disk, with only "somefolder:\" prefix. The last part is doing the magic.
This is what I came up with to solve the issue. I'm still open for better methods, as this is a bit of a hack (but seems to be accurate with the current specifications). The function expects a segment from an Uri to process (LocalPath when dealing with web requests). Example call is below..
protected String _GetResourceName( String[] zSegments )
{
// Initialize the resource string to return.
String zResource = String.Empty;
// Initialize the variables for the dot- and find position.
int iDotPos, iFindPos;
// Loop through the segments of the provided Uri.
for ( int i = 0; i < zSegments.Length; i++ )
{
// Find the first occurrence of the dot character.
iDotPos = zSegments[i].IndexOf( '.' );
// Check if this segment is a folder segment.
if ( i < zSegments.Length - 1 )
{
// A dash in a folder segment will cause each following dot occurrence to be appended with an underscore.
if (( iFindPos = zSegments[i].IndexOf( '-' )) != -1 && iDotPos != -1 )
{
zSegments[i] = zSegments[i].Substring( 0, iFindPos + 1 ) + zSegments[i].Substring( iFindPos + 1 ).Replace( ".", "._" );
}
// A dash is replaced with an underscore when no underscores are in the name or a dot occurrence is before it.
//if (( iFindPos = zSegments[i].IndexOf( '_' )) == -1 || ( iDotPos >= 0 && iDotPos < iFindPos ))
{
zSegments[i] = zSegments[i].Replace( '-', '_' );
}
}
// Each slash is replaced by a dot.
zResource += zSegments[i].Replace( '/', '.' );
}
// Return the assembly name with the resource name.
return String.Concat( _zAssemblyName, zResource );
}
Example call..
var testResourceName = _GetResourceName( new String[] {
"/",
"Scripts/",
"jQuery.UI-1.8.12/",
"jQuery-_.UI.js"
});
Roel,
Hmmm... This is a hack, but I guess it should work. Just define an empty "Marker" class in each directory which contains resources, then get the FullName of it's type, remove the class name from end and wala: there's your decoded-path.
string path = (new MarkerClass()).GetType().FullName.Replace(".MarkerClass", "");
I'm sure there's a "better" way to do it... with a LOT more lines of code; and this one has the advantage that Microsoft maintains it when they change stuff ;-)
Cheers. Keith.
A late answer here as well, I googled before I attempted this on my own and I eventually had to.
Here's the solution I came up with:
public string ProcessFolderDash(string path)
{
int dotCount = path.Split('/').Length - 1; // Gets the count of slashes
int dotCountLoop = 1; // Placeholder
string[] absolutepath = path.Split('/');
for (int i = 0; i < absolutepath.Length; i++)
{
if (dotCountLoop <= dotCount) // check to see if its a file
{
absolutepath[i] = absolutepath[i].Replace("-", "_");
}
dotCountLoop++;
}
return String.Join("/", absolutepath);
}
i try to write a query but my query finished with "Control nvarchar(500), ". i want to finish "Control nvarchar(500)" How can remove ",", " "?
void SqlTable(List listMyColumnNames, string TableName)
{
string Text = "Create table ENG_"+TableName+" (ENG_"+TableName+"_ID integer PRIMARY KEY identity(1,1), ";
char[] MyChar = {',', ' ' };
for (int i = 0; i < listMyColumnNames.Count; )
{
Text+=listMyColumnNames[i]+" nvarchar(500), ";
if (i == listMyColumnNames.Count-1)
Text.TrimEnd(MyChar);
i++;
}
Text+=" )";
I think you may want to look at String.Join. What you can do is transform your column name strings, containing the SQL definition of your colum, e.g. MyColumnName[1]+" nvarchar(500)", into alistMyColumnDefarray, thenJoin` that array with the comma as a separator.
The benefit:
no 'if I'm the last entry',
clear separation of your column names and your SQL representation for a column
The drawbacks.... none :)
for( String name in listMyColumnNames ) {
listMyColumnDefs.Add( name + " nvarchar(500)" );
}
String mycolumndef = String.Join( listMyColumnDefs, ", ");
There are many ways to fix this, but here's the problem in your code:
if (i == listMyColumnNames.Count-1)
Text.TrimEnd(MyChar); // doesn't work like this!
String is immutable: you can't invoke a method on it and expect it to be mutated by the method. TrimEnd instead returns a new String, so what you need to do is:
Text = Text.TrimEnd(MyChar); // now works fine!
Related questions
Why string.Replace(“X”,“Y”) works only when assigned to new string?
for (int i = 0; i < listMyColumnNames.Count; ++i)
{
Text += listMyColumnNames[i] + " nvarchar(500)";
if (i < listMyColumnNames.Count-1)
Text += ", ";
}
Or you could just remove your Trim call and add `Text = Text.Replace(", )", " )");' at very end.
Have you thought about using the StringBuilder object to build your string, rather than concatenating yours string in a loop!
http://www.yoda.arachsys.com/csharp/stringbuilder.html