How to Get The Range of The First Line in a String

How to get the range of the first line in a string?

A String.Index range for the first line in string can be obtained with

let range = string.lineRange(for: ..<string.startIndex)

If you need that as an NSRange then

let nsRange = NSRange(range, in: string)

does the trick.

How to get the full line range for a given character range in Swift?

lineRange(for:) (essentially) expects a range of String.Index, not a range of integers. Here is a simple example:

let string = "Line1\nLine2"

// Find the full range of the line containing the first "1":
if let range = string.range(of: "1") {
let lineRange = string.lineRange(for: range)
print(string[lineRange]) // Line1
}

The actual parameter is a generic parameter of type R : RangeExpression, R.Bound == String.Index, which means that you can also pass partial ranges like string.startIndex... or ..<string.endIndex.

The Swift version of the Objective-C sample code

NSString *string;
unsigned numberOfLines, index, stringLength = [string length];
for (index = 0, numberOfLines = 0; index < stringLength; numberOfLines++)
index = NSMaxRange([string lineRangeForRange:NSMakeRange(index, 0)]);

would be

let string = "Line1\nLine2"

var index = string.startIndex
var numberOfLines = 0
while index != string.endIndex {
let range = string.lineRange(for: index..<index)
numberOfLines += 1
index = range.upperBound
}

print(numberOfLines)

Here index..<index takes the role of NSMakeRange(index, 0).

If the purpose is just to count (or enumerate) the total number of lines then an alternative is to use

string.enumerateLines(invoking: { (line, _) in
// ...
})

instead (compare How to split a string by new lines in Swift).

How can we get the line range before another line range?

One way to do this is to get the line start of the range, then find the line range of the position before the line start:

extension NSString {
func getLineRangeBefore(_ lineRange: NSRange) -> NSRange? {
var lineStart = 0
getLineStart(&lineStart, end: nil, contentsEnd: nil, for: lineRange)
if lineStart == 0 {
return nil
}
return self.lineRange(for: NSRange(location: lineStart - 1, length: 0))
}
}

Note that this should return an optional NSRange because the range could be contained by the first line, in which case there is no line before it.

How do you bold the first line in an NSMutableParagraphStyle?

You can find the first by separating the string by newline:

let firstLine = "Happy \n Birthday".split(separator: "\n").first

This will give you the first line of the string. (long text multi lining doesn't count) then you can find the range using this and apply the bold effect.

How this works:

  • You need to set the label the way that accepts multiline:
  • Find the range of first line
  • Convert it to nsRange
  • Apply attributes to the range

Here is a fully working example:

import UIKit
import PlaygroundSupport

extension StringProtocol where Index == String.Index {

func nsRange(from range: Range<Index>) -> NSRange {
return NSRange(range, in: self)
}
}

class MyViewController : UIViewController {
override func loadView() {
let view = UIView()
view.backgroundColor = .white

let label = UILabel()
label.numberOfLines = 0
label.text = "Happy \n Birthday"
label.textColor = .black

let text = "Happy \n Birthday"
let attributedString = NSMutableAttributedString(string: text)
let firstLine = text.split(separator: "\n").first!
let range = text.range(of: firstLine)!
attributedString.addAttributes([.font : UIFont.boldSystemFont(ofSize: 14)], range: text.nsRange(from: range))
label.attributedText = attributedString
label.sizeToFit()

view.addSubview(label)
self.view = view
}
}

PlaygroundPage.current.liveView = MyViewController()

Get string of first line in a UILabel

1.Add CoreText.framework. 2. Import #import CoreText/CoreText.h>.
Then use below method -

-(NSArray *)getLinesArrayOfStringInLabel:(UILabel *)label
{
NSString *text = [label text];
UIFont *font = [label font];
CGRect rect = [label frame];

CTFontRef myFont = CTFontCreateWithName(( CFStringRef)([font fontName]), [font pointSize], NULL);
NSMutableAttributedString *attStr = [[NSMutableAttributedString alloc] initWithString:text];
[attStr addAttribute:(NSString *)kCTFontAttributeName value:( id)myFont range:NSMakeRange(0, attStr.length)];

CFRelease(myFont);

CTFramesetterRef frameSetter = CTFramesetterCreateWithAttributedString(( CFAttributedStringRef)attStr);

CGMutablePathRef path = CGPathCreateMutable();
CGPathAddRect(path, NULL, CGRectMake(0,0,rect.size.width,100000));

CTFrameRef frame = CTFramesetterCreateFrame(frameSetter, CFRangeMake(0, 0), path, NULL);

NSArray *lines = ( NSArray *)CTFrameGetLines(frame);

NSMutableArray *linesArray = [[NSMutableArray alloc]init];

for (id line in lines)
{
CTLineRef lineRef = ( CTLineRef )line;
CFRange lineRange = CTLineGetStringRange(lineRef);
NSRange range = NSMakeRange(lineRange.location, lineRange.length);

NSString *lineString = [text substringWithRange:range];

CFAttributedStringSetAttribute((CFMutableAttributedStringRef)attStr, lineRange, kCTKernAttributeName, (CFTypeRef)([NSNumber numberWithFloat:0.0]));
CFAttributedStringSetAttribute((CFMutableAttributedStringRef)attStr, lineRange, kCTKernAttributeName, (CFTypeRef)([NSNumber numberWithInt:0.0]));

//NSLog(@"''''''''''''''''''%@",lineString);
[linesArray addObject:lineString];

}
[attStr release];

CGPathRelease(path);
CFRelease( frame );
CFRelease(frameSetter);

return (NSArray *)linesArray;
}

I found this answer from below url - How to get text from nth line of UILabel?

NSString *firstLineString = [[self getLinesArrayOfStringInLabel:yourLabel] objectAtIndex:0];

How can I extract a predetermined range of lines from a text file on Unix?

sed -n '16224,16482p;16483q' filename > newfile

From the sed manual:

p -
Print out the pattern space (to the standard output). This command is usually only used in conjunction with the -n command-line option.

n -
If auto-print is not disabled, print the pattern space, then, regardless, replace the pattern space with the next line of input. If
there is no more input then sed exits without processing any more
commands.

q -
Exit sed without processing any more commands or input.
Note that the current pattern space is printed if auto-print is not disabled with the -n option.

and

Addresses in a sed script can be in any of the following forms:

number
Specifying a line number will match only that line in the input.

An address range can be specified by specifying two addresses
separated by a comma (,). An address range matches lines starting from
where the first address matches, and continues until the second
address matches (inclusively).

How to detect whether a specific range from string is in the newline?

Try using onselect event , storing each line of input text within an array, checking each line for saved variable using RegExp \n . See also Getting currently selected text

var textarea = document.querySelector("textarea"), re = /\n/;
textarea.onselect = function(e) { var res = []; // current selection var sel = this.value.slice(this.selectionStart, this.selectionEnd); // create array of input value split at new line characters var matches = this.value.split(re); // split input value at new line characters // return `true` or `false` var selected = sel.split(re); for (var i = 0; i < selected.length; i++) { if (matches.indexOf(selected[i]) !== -1) { res.push(true) } else { res.push(false) } }
console.log(matches, res, selected)}
<textarea style="width:300px;height:200px">  this is test1  this is test2  this is test3</textarea>

Im trying to string search from a range of lines in a text file but the stringsearch outputs empty

Suggestions

  1. Variable naming

Why line2 followed by line1? Better to name in successive order i.e. line1, line2.

Or even better relate variable name to its purpose and use Python naming convention thus:

starting_line, ending_line, search_string, search_results

  1. Use in rather than __ contains__

Like all "Dunder" or "special methods" identified by names that begin and end with __, contains is not meant to be called directly but, in very specific cases Reference


  1. lines contain your array of lines, so use slicing to get the desired lines i.e.

    lines[starting_line:ending_line+1]

Answer to Original Question

starting_line = int(input("What starting line number do you need? "))
ending_line = int(input("What closing line number do you need? "))
search_string = input("What string do you like to search in this test case: ")

search_results = []
with open('texfile') as f:
lines = f.readlines()
for index, line in enumerate(lines[starting_line:ending_line+1], start = starting_line):
# Used slicing to filter to lines to search
if search_string in line:
line = line.rstrip() # remove the newline at end of line
search_results.append(line)
print (f'Found string in line number {index} containing {line}')

Answer to Revised Question

def get_groups(file, start_line, end_line):
'''
Finds multiple groups of data lines

file - file path
start_line - substring for starting line
end_line - substring for ending line
'''
with open(file) as f:
result = []
processing_group = False
for line in f:
line = line.rstrip()
if start_line in line:
# Start new group
result.append([])
result[-1].append(line) # First line of group
processing_group = True
elif end_line in line and processing_group:
result[-1].append(line) # last line of group
processing_group = False
elif processing_group:
result[-1].append(line) # Add this line to current group

return result

Usage

res = get_groups('test_cases.txt', 'src=testCaseEntering', 'src=testCaseEntering')
for group in res:
print('Test Case')
print(*group, sep = '\n')

File: 'test_cases.txt'

2021.02.28.19.12.31.121605] 1500790 [in=][src=main] sz_right <60>
[2021.02.28.19.12.31.124834] 1500793 [in=][src=main] sz_right </opt/svgCppTests/adi_wil_cfg_profile-2_24_100ms.cfg>
[2021.02.28.19.12.31.192254] 1500861 [in=][src=main] gDSessionConfig->nodeVersionMajorMF <0>
[2021.02.28.19.12.31.771470] 1501440 [in=][src=connect] Connected
[2021.02.28.19.12.32.892645] 1502561 [in=testAclEntrySetGet_INPSVG1297][src=testCaseEntering] testCaseEntered
[2021.02.28.19.12.34.114328] 1503783 [in=][src=getNetworkStatus]
5118136 [in=]error _rcCallback <1>
[2021.02.28.19.12.31.124834] 1500793 [in=][src=main] sz_right
[2021.02.28.20.12.50.643308] 5120312 [in=][src=setMode]
[2021.02.28.20.14.37.608403] 5227277 [in=testModesAll_INPSVG1367][src=testCaseExiting] ================================== Fail ===================================
[2021.02.28.19.12.32.892645] 1502559 [in=testAclEntrySetGet_INPSVG1297][src=testCaseEntering]
[2021.02.28.19.12.31.124834] 1500888 [in=][src=main] sz_right
[2021.02.28.19.12.31.124834] 1500888 [in=][src=main] sz_right
[2021.02.28.19.12.31.124834] 1500888 [in=][src=main] sz_right
[2021.02.28.20.14.37.608403] 5337289 [in=testModesAll_INPSVG1367][src=testCaseExiting]
[2021.02.28.19.12.32.892645] 1502559 [in=testAclEntrySetGet_INPSVG1297][src=testCaseEntering]
[2021.02.28.20.12.50.643308] 5120312 [in=][src=setMode]
[2021.02.28.20.14.37.608403] 5337289 [in=testModesAll_INPSVG1367][src=testCaseExiting] ================================== Fail ===================================
[2021.02.28.19.12.32.892645] 1502559 [in=testAclEntrySetGet_INPSVG1297][src=testCaseEntering]
[2021.02.28.20.14.38.401407] 5228070 [in=][src=connect] Connected
[2021.02.28.20.14.37.608403] 5337289 [in=testModesAll_INPSVG1367][src=testCaseExiting]

Output

Test Case
[2021.02.28.19.12.32.892645] 1502561 [in=testAclEntrySetGet_INPSVG1297][src=testCaseEntering] testCaseEntered
[2021.02.28.19.12.34.114328] 1503783 [in=][src=getNetworkStatus]
5118136 [in=]error _rcCallback <1>
[2021.02.28.19.12.31.124834] 1500793 [in=][src=main] sz_right
[2021.02.28.20.12.50.643308] 5120312 [in=][src=setMode]
[2021.02.28.20.14.37.608403] 5227277 [in=testModesAll_INPSVG1367][src=testCaseExiting] ================================== Fail ===================================
Test Case
[2021.02.28.19.12.32.892645] 1502559 [in=testAclEntrySetGet_INPSVG1297][src=testCaseEntering]
[2021.02.28.19.12.31.124834] 1500888 [in=][src=main] sz_right
[2021.02.28.19.12.31.124834] 1500888 [in=][src=main] sz_right
[2021.02.28.19.12.31.124834] 1500888 [in=][src=main] sz_right
[2021.02.28.20.14.37.608403] 5337289 [in=testModesAll_INPSVG1367][src=testCaseExiting]
Test Case
[2021.02.28.19.12.32.892645] 1502559 [in=testAclEntrySetGet_INPSVG1297][src=testCaseEntering]
[2021.02.28.20.12.50.643308] 5120312 [in=][src=setMode]
[2021.02.28.20.14.37.608403] 5337289 [in=testModesAll_INPSVG1367][src=testCaseExiting] ================================== Fail ===================================
Test Case
[2021.02.28.19.12.32.892645] 1502559 [in=testAclEntrySetGet_INPSVG1297][src=testCaseEntering]
[2021.02.28.20.14.38.401407] 5228070 [in=][src=connect] Connected
[2021.02.28.20.14.37.608403] 5337289 [in=testModesAll_INPSVG1367][src=testCaseExiting]



Related Topics



Leave a reply



Submit