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 -
Exitsed
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
- 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
- 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
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
Type Alias Declaration with Templates in Swift
How to Apply Impulse to The Node on Touch Angle
Swift: Draw a Semi-Sphere in Mkmapview
Nssavepannel - How to Restrict User to Only Save One One Set Directory
How to Add Skspritenode in a Loop
Swift - Rotate Gesture and Rotation Increments of 90 Degrees
Protocol with Associatedtype Protocol for Generic Functions
Trim Video Always Fail When Use Avassetexportpresetpassthrough
How to Fix Dylib with Invalid Signature
Swift Xml Rss Reader... Make It Async
Playing Multiple Wav Out Multiple Channels Avaudioengine
Query Value Between Two Other Values in Firebase
Transparent Sticky Header UI Collectionview Don't Show Cells Underneath