How can I cut text in AppleScript and BBEdit? - text

In a text file given the following text:
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
Sunday
with AppleScript and BBEdit I'd like to be able to cut the day Sunday and move it before Monday but when I reference the BBEdit dictionary I see the ability to cut:
when I try to cut the text and add it before the line I get an error:
BBEdit got an error: "Sunday" doesn’t understand the “cut” message.
the code:
tell application "BBEdit"
set theFile to "foobar.txt"
select insertion point before first character of text document theFile
repeat
set theWeekend to find "(?<=Saturday\\n)Sunday" searching in text 1 of text document theFile options {search mode:grep} with selecting match
if theWeekend is not found then exit repeat
set theWeekend to found text of theWeekend
select insertion point before first character of text document theFile
set beforeMon to find "(?!<=Sunday\\n)Monday" searching in text 1 of text document theFile options {search mode:grep} with selecting match
if beforeMon is found then
set beforeMon to found text of beforeMon
set theLine to startLine of selection
set addDay to select insertion point before first character of line theLine of text document theFile
set thePull to cut theWeekend ## where error occurs
set before line theLine of text of text document theFile to (theWeekend & return)
end if
end repeat
end tell
If I comment out set thePull to cut theWeekend the script works in a continuous loop and places Sunday before Monday but I can't break the loop because my grep variable theWeekend is still false.
Other failed attempts:
cut selection of (theWeekend)
cut theWeekend
cut theWeekend of selection
cut selection of contents of (theWeekend)
cut contents of theWeekend
In BBEdit and AppleScript how can I cut the day and move it?

The error is that the theWeekend variable contains a string, not a reference to a string.
The cut command need a reference to a (character, word or line) in the document, like this:
cut characters 51 thru 56 of text document 1
cut line 7 of text document 1
cut word 7 of text document 1
cut selection -- or this
So use the found object property instead of the found text.
tell application "BBEdit"
activate
tell text document "foobar.txt"
select insertion point before first character
repeat
set theWeekend to find "(?<=Saturday\\n)Sunday" searching in text 1 options {search mode:grep} with selecting match
if theWeekend is not found then exit repeat
select insertion point before first character
set beforeMon to find "(?!<=Sunday\\n)Monday" searching in text 1 options {search mode:grep} with selecting match
if beforeMon is found then
cut (found object of theWeekend) -- the cut command returns nothing, it's useless to put the result in a variable
set before (found object of beforeMon) to (found text of theWeekend) & return
end if
end repeat
end tell
end tell

Here is a modified version of your code that worked for me in testing:
I removed the set theWeekend to found text of theWeekend line completely, while modifying:
set before line theLine of text of text document theFile to (theWeekend & return)
To:
set before line theLine of text of text document theFile to (found text of theWeekend & linefeed)
theWeekend in this case is a list returned from the find command, leave it as a list because you actually need to use two of the properties from it.
found text in this instance and also found object in the set thePull to cut ... line above this.
I typically use linefeed instead of return because in some instances, although not this one, the latter does end up as 0D instead of 0A. In other words, it ends up as a \r and not what is typical, \n in macOS documents.
I also changed set thePull to cut theWeekend, to:
set thePull to cut (found object of theWeekend)
Reworked AppleScript code:
tell application "BBEdit"
set theFile to "foobar.txt"
select insertion point before first character of text document theFile
repeat
set theWeekend to find "(?<=Saturday\\n)Sunday" searching in text 1 of text document theFile options {search mode:grep} with selecting match
log theWeekend
if theWeekend is not found then exit repeat
select insertion point before first character of text document theFile
set beforeMon to find "(?!<=Sunday\\n)Monday" searching in text 1 of text document theFile options {search mode:grep} with selecting match
if beforeMon is found then
set beforeMon to found text of beforeMon
set theLine to startLine of selection
set addDay to select insertion point before first character of line theLine of text document theFile
set thePull to cut (found object of theWeekend)
set before line theLine of text of text document theFile to (found text of theWeekend & return)
end if
end repeat
end tell

Related

Delete text that begin with a specific character in a txt file

I have a txt file in this format (a list of numbers)
123456
654321
0123456
01564
98789
I want to delete all the lines that begins with a 0. How could this be done?
How about:
Find what: ^0.*\R
Replace with: NOTHING
Do not check . matches newline

Multilevel parsing using shell command

I have a file in the following format
/////
name 1
start_occurrence:
occurrence 1
occurrence 2
///
name 2
start_occurance:
occurrence 1
occurrence 2
///
name 3
start_occurrence:
occurrence 1
occurrence 2
occurrence 3
All I need is to make a count of the number of occurrences for each name and save them in a CSV file. Can I do it using any combination of shell commands? Yes I can do it programmatically, but looking for a bunch of shell commands in a pipe lined fashion.
"names" can be anything. Names does not come with a pattern. Only catch is that the line after /// is the name. Also Occurrence does not have any number with it, anyline that starts with occurrence or have occurrence is a subject of interest.
awk 'c=="THISISNAME"{b=$0;c="";}$1=="///"{c="THISISNAME"}$0~/\<occurrence\>/{a[b]+=1;}END{for (i in a){print i" "a[i]}}' YOUR_FILE_HERE
explain:
if match the name start condition ($1=="///"), mark the c to THISISNAME.
if this is the name line (c=="THISISNAME"), mark the name line with b, and mark c as name part ended(c="").
if match the occurrence condition ($0~/\<occurrence\>/), make a[b] += 1.
use a map a to remark the occurrence time of each name.
awk use EREs, the $0~/EREs/ means $0 match the regex. the '\<' and '>' means '\b' in PREs

Append string to column on command line

I have a 3 column file. I would like to append a third column which is just one word repeated many times. I tried the following
paste file.tsv <(echo 'new_text') > new_file.tsv
But the text 'new_text' only appears on the first line, not every line.
How can I get 'new_text' to appear on every line.
Thanks
sed '1,$ s/$/;ABC/' infile > outfile
This replaces the line end ("$") with ";ABC".

Keep duplicate lines notepad++

I need to remove the unique lines and keep the duplicates in my text file(read the articles written to remove duplicate lines but I want to do the opposite). Is there any way I could do that using expressions or textfx?
E.g:
file1.txt
hello
world
hello
After operation, output should be
hello
hello
Thanks in advance
In the Replace dialogue:
Find:
^(.+)\r?\n(?!(.|\r?\n)*\1)
Replace:
*leave empty!*
Options:
Select radio button "Regular Expression"
Leave checkbox ". matches newline" unselected
Pros:
Duplicate line doesn't need to be immediately after the 1st occurrence
Cons:
If a line appears x times in your data, after the regex x-1 occurrences will be left and not x as asked in OP.
This finds all lines followed by a line repetition (it does NOT find the last line, though):
.+\r\n(?=(.+\r\n)\1)
000000 111111 22
This matches a non-empty line 0, but only if it is followed by (a non-empty line \1, which is followed by \1).
Note that this assumes \r\n (Windows) line separations. On a Unix text file, just \n, on a Mac text file, just \r.
In the search box, mark Regular expression, unmark . matches newline, Replace with = "".
Example:
"Zulu
Alpha
Alpha
Bravo
Charlie
Charlie
Delta
Echo
Echo
Foxtrott
"
(file ends with empty line)
-->
"Alpha
Alpha
Charlie
Charlie
Echo
Echo
Foxtrott
"

Vim: Replace n with n+1

How do I replace every number n that matches a certain pattern with n+1? E.g. I want to replace all numbers in a line that are in brackets with the value+1.
1 2 <3> 4 <5> 6 7 <8> <9> <10> 11 12
should become
1 2 <4> 4 <6> 6 7 <9> <10> <11> 11 12
%s/<\zs\d\+\ze>/\=(submatch(0)+1)/g
By way of explanation:
%s " replace command
"""""
< " prefix
\zs " start of the match
\d\+ " match numbers
\ze " end of the match
> " suffix
"""""
\= " replace the match part with the following expression
(
submatch(0) " the match part
+1 " add one
)
"""""
g " replace all numbers, not only the first one
Edit:
If you only want to replace in specific line, move your cursor on that line, and execute
s/<\zs\d\+\ze>/\=(submatch(0)+1)/g
or use
LINENUMs/<\zs\d\+\ze>/\=(submatch(0)+1)/g
(replace LINENUM with the actual line number, eg. 13)
In vim you can increment (decrement) the numeric digit on or after the cursor by pressing
NUMBER<ctrl-a> to add NUMBER to the digit
(NUMBER<ctrl-x> to substract NUMBER from the digit)
If only incrementing (decrementing) by one you don't need to specify NUMBER. In your case I would use a simple macro for this:
qaf<<ctrl-a>q
100<altgr-q>a
Here a brief explanation of the macro: It uses the find (f) commant to place the cursor on the opening < bracket. It is not necessary to position the cursor on the digit. When press the number on the cursor or the nearest number after the cursor will get incremented.
If you want an even shorter series of commands you can position your curser ONCE by pressing f<, increment the number with ctrl-a and then just repeatedly press ;.. The ; command repeats the last cursor movement i.e. the find command. The . command repeats the last text changing command.
Check out this link for further information or use the built in documentation: h: ctrl-a.

Resources