Come eliminare una riga specifica di un paragrafo in AppleScript, mantenendo il formato originale del testo?


-1

Ho una variabile di testo di classe textche mostra qualcosa del genere quando viene restituito:

"
This is sentence 1.
This is sentence 2.
This is sentence 3.
This is sentence 4."

Voglio essere in grado di eliminare righe specifiche dal testo, senza influire sul resto della variabile.

Ad esempio: delete {1, 3}per ottenere questo risultato:

"This is sentence 1.
This is sentence 3.
This is sentence 4."

Il metodo descritto in questa risposta ha un bug grave:

"Come eliminare una riga specifica di un paragrafo in AppleScript?"

Il metodo collegato per eliminare le righe in un paragrafo in realtà converte tutti gli avanzamenti di riga nella variabile di testo in ritorni. In altre parole, è impossibile eseguire questo codice più di una volta sulla stessa variabile.

Ad esempio, il seguente codice:

set varText to "
This is sentence 1.
This is sentence 2.
This is sentence 3.
This is sentence 4."
set varText to do shell script "sed -e '1d;3d' <<< " & quoted form of varText
-- Employing the same method on the same variable:
set varText to do shell script "sed -e '1d;3d' <<< " & quoted form of varText
return varText

ritorna

""

Poiché questo metodo funziona correttamente solo se le righe della variabile di testo sono il prodotto di una linefeed(come dovrebbe), il problema non è che questo metodo non riesce a percepire returnuna nuova riga (come avevo inizialmente sostenuto in questa domanda). Il problema è che questo codice introduce returninnanzitutto una variabile di testo.


Quindi, voglio una soluzione che mi permetta di eseguire la stessa variabile di testo attraverso la soluzione più di una volta nello stesso AppleScript.

In altre parole, sto cercando un metodo per rimuovere una riga specifica da un paragrafo che non ha questo bug e non inserisce un returnpunto nel testo.


Per quanto riguarda le informazioni nella tua Modifica:: il do shell script "sed ..." comando quando eseguito nel Terminale varTextrestituisce con \n(x0A) non \r(x0D) come dovrebbe. Anche il do shell script "sed ..." comando compilato in Script Editor ha ancora \n(x0A) non \r(x0D) tuttavia il motivo per cui viene restituito con \r(x0D) l'intenzione del previsto \n(x0A) è un mistero per me al momento. Lo considererò un bug di AppleScript poiché non rispecchia il comportamento previsto dello stesso quando eseguito in Terminal. Questo è il motivo per cui ho eliminato la mia risposta perché non ero a conoscenza del problema.
user3439894

GrahamMiln Da allora ho identificato il bug con la risposta originale che mi ha portato a pubblicare la seconda domanda, è possibile unire queste due domande? In caso contrario, puoi semplicemente eliminare completamente questa domanda, poiché @ user3439894 ha fornito la risposta aggiornata sulla seconda domanda?
Sfera di Rubik

Non voglio eliminare questa domanda da solo, perché ciò comporterà uno sciopero contro il mio account SE. (Capisco che l'atto di eliminare la propria domanda è penalizzato).
Sfera di Rubik

Per quanto riguarda il tuo utilizzo return, sono ovviamente d'accordo! In realtà, non uso e non ho mai usato returnper concatenare stringhe multilinea! Ecco perché ho dovuto modificare in modo significativo il titolo e il corpo di questa domanda; il mio post conteneva diverse dichiarazioni inesatte. Questo post è stato pubblicato per la prima volta prima che mi accorgessi del bug nel tuo codice, che (alla fine ho capito) spiegava da dove returnsprovenivano tutte le variabili del mio testo! Inizialmente avevo supposto di essere stato - in qualche modo - responsabile della prevalenza dei returnpersonaggi, cosa che ora non so.
Sfera di Rubik

Prima di tutto non era il mio codice in sé che aveva il bug! È un bug nel modo in cui il do shell script comando sta elaborando ciò che viene restituito dalla riga di comando , è AppleScript che non elabora correttamente l'output dei comandi eseguiti all'interno del do shell script comando ! L'utilizzo di returnuna concatenazione di stringhe a più linee era un problema perché sedha visto il contenuto della variabile come una riga e cancellato perché è in attesa di x0Anon x0Dallinearsi finali. Comunque la mia risposta aggiornata gestisce sia il cattivo utilizzo di returnover linefeedche il bug.
user3439894

Risposte:


1

Ok, ho eliminato l'originale e la prima modifica perché hai modificato la tua domanda originaria al punto che è più facile scrivere una nuova risposta del tutto.

Poiché la tua domanda iniziale mostrava la seguente riga di codice , come esempio di come può essere impostata la variabile, la includerò per dire quanto segue.

Se varTextè stato impostato, ad esempio:

set varText to (return & "This is sentence 1." & return & "This is sentence 2." & return & "This is sentence 3." & return & "This is sentence 4.")
  • In quale returnè invece x0Dl'uso più appropriato di linefeed( x0A) invece, nel caso in cui la variabile sia data e non un messaggio usa e getta.

O:

set varText to "
This is sentence 1.
This is sentence 2.
This is sentence 3.
This is sentence 4."
  • In cui ciascuna di queste righe termina in realtà con un linefeed( x0A) come dovrebbe essere su un Mac.

Il do shell script comando ha un bug in quanto converte x0Aa x0Ddopo quello che è tornato dalla riga di comando con le attese x0Afinali ripassato. L'ho confermato perché se utilizzo quanto segue:

set varText to "
This is sentence 1.
This is sentence 2.
This is sentence 3.
This is sentence 4."

set varText to do shell script "sed  -e '1d;3d' <<< " & quoted form of varText & " | tee $HOME/Desktop/outfile"

Quindi outfilecontiene linefeed( x0A) le terminazioni in modo che lo stesso venga restituito do shell scriptma converte erroneamente le x0Aterminazioni di linea in x0Dterminazioni che possono quindi essere gestite come segue:

Quindi, per sistemare il bug , assicurati sempre che il contenuto della variabile passata e restituita contenga x0Aterminazioni di riga usando il seguente codice dihandler esempio .

Di seguito si presume che varTextsia già stato impostato da uno dei metodi sopra descritti.

on ensureLinesEndWith0A(varText)
    set varText to paragraphs of varText
    set oldTID to AppleScript's text item delimiters
    set AppleScript's text item delimiters to linefeed
    set varText to varText as string
    set AppleScript's text item delimiters to oldTID
    return varText
end ensureLinesEndWith0A

set varText to ensureLinesEndWith0A(varText)
set varText to do shell script "sed  -e '1d;3d' <<< " & quoted form of varText
set varText to ensureLinesEndWith0A(varText)

È quindi possibile utilizzare nuovamente quanto segue per eliminare più righe da varText:

set varText to ensureLinesEndWith0A(varText)
set varText to do shell script "sed  -e '1d;3d' <<< " & quoted form of varText
set varText to ensureLinesEndWith0A(varText)

L'immagine seguente mostra un esempio di chiamata al do shell script " sed ..." comando due volte.

immagine di esempio di codice


Sfera di rubik @, controlla l'immagine che ho aggiunto alla mia risposta.
user3439894

Ho testato la tua text item delimiters to linefeedsoluzione alternativa. Credo che correggi con successo il piccolo bug pernicioso AppleScript che abbiamo identificato. Ora posso eseguire innumerevoli do shell script "sed -e...operazioni sulla stessa variabile di testo all'interno della stessa esecuzione di uno script e le righe specificate vengono eliminate in modo affidabile come previsto. Grazie per l'aiuto!
Sfera di Rubik

1

Esempio:

set varText to "
This is sentence 1.
This is sentence 2.
This is sentence 3.
This is sentence 4."

set varText to do shell script "sed -e '1d;3d' <<< " & quoted form of varText

Ritorna:

"This is sentence 1.
This is sentence 3.
This is sentence 4."

Aggiornamento: a seguito di una scoperta menzionata in Modifica: di Come eliminare una riga specifica di un paragrafo basato su "return" in AppleScript? , vorrei fare la seguente dichiarazione:

NOTA: Sfortunatamente ciò che viene restituito in questo caso ha caratteri di ritorno a capo (x0D) invece dei caratteri di nuova riga previsti (x0A) e secondo me è un bug!

È un bug perché: il do shell script "sed ..." comando eseguito in Terminal con quello varTextrestituisce con \n(x0A) non \r(x0D) come dovrebbe. Anche il do shell script "sed ..." comando compilato in Script Editor ha ancora \n(x0A) non \r(x0D), tuttavia il motivo per cui viene restituito con \r(x0D) l'intenzione del previsto \n(x0A) è un mistero per me al momento e lo considererò un AppleScript bug poiché non rispecchia il comportamento previsto dello stesso quando eseguito nel Terminale.

Quindi, per tenere conto del bug nei risultati del do shell script "sed ..." comando , ecco come lo gestirò. Dopo il do shell script "sed ..." comando utilizzare le seguenti righe di codice :

set newLine to "\n"
set varText to paragraphs of varText
set oldTID to AppleScript's text item delimiters
set AppleScript's text item delimiters to newLine
set varText to varText as string
set AppleScript's text item delimiters to oldTID

Ora, ciò che è restituito contiene una nuova serie (x0a) personaggi come avrebbe dovuto cominciare con se non ci fosse questo bug, non di ritorno a capo (x0d) caratteri .


Nota: una volta compilata, la set newLine to "\n"riga di codice verrà visualizzata come di seguito:

set newLine to "
"

Se rimuovo solo una riga, mi suggerisce di includere il punto e virgola? L'ho provato in entrambi i modi (con e senza il punto e virgola) e sembra funzionare bene in entrambi i modi, ma sto solo chiedendo la tua preferenza.
Sfera di Rubik

Sfera di @ rubik, Il punto e virgola è necessario solo come separatore quando viene specificato più di un intervallo, in questo caso d'uso. Quale linea vuoi eliminare?
user3439894

Hai visto l'ultima parte della mia nuova domanda? È impossibile eseguire questo metodo due volte sulla stessa variabile, il che significa che il metodo di eliminazione della riga modifica i caratteri della nuova riga (x0A) in qualcos'altro (nel processo di eliminazione di una riga).
sfera di rubik,

0

Suddividiamo questo script in pezzi più piccoli e poi riuniamolo in un unico AppleScript.

Questo approccio è interamente scritto in AppleScript e non richiede strumenti esterni. L'uso di strumenti esterni, come perlo sed, probabilmente porterà a soluzioni molto più brevi ma hai menzionato in altre domande che vogliono imparare AppleScript.

1. Dividi con delimitatori

È possibile utilizzare il comportamento dei delimitatori di AppleScript per dividere una stringa . È possibile modificare il delimitatore come desiderato per return, linefeedo anche personaggi come =:

 -- http://macscripter.net/viewtopic.php?id=24473
 to split(someText, delimiter)
     set AppleScript's text item delimiters to delimiter
     set someText to someText's text items
     set AppleScript's text item delimiters to {""} --> restore delimiters to default value
     return someText
 end split

 set myText to (return & "This is sentence 1." & return & "This is sentence 2." & return & "This is sentence 3." & return & "This is sentence 4.")
 set myLines to split(myText, return)

2. Elenco filtri

Con l'elenco restituito, è possibile filtrare gli elementi indesiderati utilizzando un ciclo:

 -- http://macscripter.net/viewtopic.php?id=24525
 set indexesToDelete to {1, 4}
 set cleanList to {}

 repeat with i from 1 to count myLines
     if i is not in indexesToDelete then set cleanList's end to myLines's item i
 end repeat

3. Combina gli oggetti

L'elenco filtrato di frasi può essere ricombinato utilizzando un altro ciclo:

-- Combine the filtered list into a string
set myResult to ""
repeat with i from 1 to count cleanList
    if myResult is "" then
        set myResult to cleanList's item i
    else
        set myResult to myResult & return & cleanList's item i
    end if
end repeat

Interamente AppleScript

La combinazione di questi frammenti genera il seguente codice:

-- Get the text to work with
set myText to (return & "This is sentence 1." & return & "This is sentence 2." & return & "This is sentence 3." & return & "This is sentence 4.")

-- Split the text into lines based on 'return' delimiter
set myLines to split(myText, return)

-- Filter out indexes 1 and 4 using a loop
set indexesToDelete to {1, 4}
set cleanList to {}
repeat with i from 1 to count myLines
    if i is not in indexesToDelete then set cleanList's end to myLines's item i
end repeat

-- Combine the filtered list into a string
set myResult to ""
repeat with i from 1 to count cleanList
    if myResult is "" then
        set myResult to cleanList's item i
    else
        set myResult to myResult & return & cleanList's item i
    end if
end repeat

-- Final string
myResult

to split(someText, delimiter)
    set AppleScript's text item delimiters to delimiter
    set someText to someText's text items
    set AppleScript's text item delimiters to {""} --> restore delimiters to default value
    return someText
end split

Lo script sopra potrebbe essere ridotto combinando i cicli di filtro e ricombinazione. Li ho lasciati come compiti separati per dimostrare meglio i loro ruoli.


La tua strategia soffre anche dello stesso esatto bug trovato nel metodo originale fornito da @ user3439894 (il bug è descritto nella parte "Modifica:" del mio post). Ad esempio, se myTextcontiene avanzamenti di riga anziché restituiti e si utilizza la riga: set myLines to split(myText, linefeed)il codice convertirà tutti gli avanzamenti di riga esistenti nel testo in un ritorno, rendendo impossibile per la stessa variabile di testo eseguire correttamente il metodo più di una volta. Speravo in una soluzione che non avesse questo problematico effetto collaterale; Voglio eliminare le righe dalla stessa variabile più di una volta.
Sfera di Rubik

1
Sfera di @ rubik, la risposta di Graham Miln non soffre dello stesso bug poiché non sta usando un do shell script comando , che è dove si trova il bug. Sta usando returnproprio come hai mostrato nella versione originale di questa domanda! Si consiglia di non utilizzare returnper concatenare multilinea stringhe , è necessario utilizzare linefeedinvece. È un dato di fatto, se è stato sostituito tutti essere l'ultimo returna linefeednella sua risposta che avrebbe funzionato come previsto, mantenendo x0Afine riga contro il x0Dquale returnfa quando viene utilizzato come una textspeciale costante carattere della stringa di classe.
user3439894

@ user3439894 Hai ragione nel dire che tecnicamente non si tratta dello "stesso" bug. Per essere chiari, il metodo di Graham ha un bug diverso, ma uno con lo stesso effetto del bug nel tuo do shell scriptmetodo. Questo è il test: usando gli avanzamenti di riga al posto dei ritorni nella risposta di Graham, puoi eseguire una specifica variabile di testo attraverso il suo metodo più di una volta nello stesso script con tutto ancora funzionante correttamente (ad esempio, cancellando prima la seconda riga del paragrafo e quindi eliminare la terza riga, in due istruzioni separate)?
Sfera di Rubik
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.