Попробуйте этот простой конвертер "Happy to Glad" (и номер строки).
Цель этого блестящего приложения: с учетом текстового файла преобразовать все вхождения строки happy
(с учетом регистра) в glad
. Входной файл, для демонстрации:
This is a happy file.
It attempts to be very happy.
И пример приложения, используя простой двухэтапный командный процесс.
Обновление : я обновил его, чтобы обеспечить (1) прогресс и (2) загрузку каждого файла. Вам, если вы хотите отключить одну или другую загрузку.
library(shiny)
library(future)
library(promises)
plan(transparent)
ui <- fluidPage(
titlePanel("\"Happy\" to \"Glad\"!"),
sidebarLayout(
sidebarPanel(
fileInput("infile", "Upload a text file:"),
tags$hr(),
actionButton("act", "Convert!"),
tags$hr(),
splitLayout(
downloadButton("download1", label = "Download 1!"),
downloadButton("download2", label = "Download 2!")
)
),
mainPanel(
textAreaInput("intext", label = "Input", rows = 3),
tags$hr(),
textAreaInput("outtext", label = "Gladified", rows = 3)
)
)
)
server <- function(input, output, session) {
outfile1 <- reactiveVal(NULL)
outfile2 <- reactiveVal(NULL)
observeEvent(input$act, {
req(input$infile)
prog <- Progress$new(session)
prog$set(message = "Step 1 in progress",
detail = "This may take a few moments...",
value = NULL)
future({
Sys.sleep(2)
outf1 <- tempfile()
ret1 <- system2("sed", c("-e", "s/happy/glad/g",
shQuote(input$infile$datapath)),
stdout = outf1)
if (ret1 == 0L && file.exists(outf1)) {
outfile1(outf1)
} else outf1 <- NULL
outf1
}) %...>%
{
inf <- .
if (is.null(inf) || !file.exists(inf)) {
prog$set(message = "Problems with Step 1?",
detail = "(process interrupted ...)",
value = NULL)
} else {
prog$set(message = "Step 2 in progress",
detail = "This may take a few moments...",
value = NULL)
}
inf
} %...>%
{
future({
inf <- .
if (!is.null(inf) && file.exists(inf)) {
Sys.sleep(2)
outf2 <- tempfile()
ret2 <- system2("cat", c("-n", shQuote(inf)),
stdout = outf2)
if (ret2 == 0L && file.exists(outf2)) {
outfile2(outf2)
} else outf2 <- NULL
}
list(inf, outf2)
})
} %...>%
{
inf <- .
if (is.null(inf[[1]])) {
# do nothing, we already saw the progress-error
} else if (is.null(inf[[2]]) || !file.exists(inf[[2]])) {
prog$set(message = "Problems with Step 2?",
detail = "(process interrupted ...)",
value = NULL)
} else outfile2(inf[[2]])
} %>%
finally(~ prog$close())
})
observeEvent(input$infile, {
req(input$infile$datapath, file.exists(input$infile$datapath))
txt <- readLines(input$infile$datapath, n = 10)
updateTextAreaInput(session, "intext", value = paste(txt, collapse = "\n"))
})
observeEvent(outfile2(), {
req(outfile2(), file.exists(outfile2()))
txt <- readLines(outfile2(), n = 10)
updateTextAreaInput(session, "outtext", value = paste(txt, collapse = "\n"))
})
output$download1 <- downloadHandler(
filename = function() {
req(input$infile)
paste0(basename(input$infile$name), "_gladified")
},
content = function(file) {
req(outfile1())
file.copy(outfile1(), file)
}
)
output$download2 <- downloadHandler(
filename = function() {
req(input$infile)
paste0(basename(input$infile$name), "_gladified_and_numbered")
},
content = function(file) {
req(outfile2())
file.copy(outfile2(), file)
}
)
}
shinyApp(ui, server)
Примечания:
- Это не очень умно, поэтому для каждого
if (ret1 == 0L)
вы должны иметь предложение else
, которое представляет какое-то сообщение об ошибке пользователю, если оно не равно нулю;
- Это немного неэффективно, потому что он делает копию выходного файла, а не переименовывает его. Я выбрал это, потому что переименование разрешит загрузку только один раз.
- Я не тратил много времени на устранение неполадок, возникающих при неудачной обработке; хотя я думаю, что маркеры прогресса, которые я поставил, являются приличными, вам может потребоваться дополнительное тестирование состояний отказа;
- Вероятно, было бы полезно включить в кнопки загрузки
shinyjs::toggleState
, чтобы вы не могли загрузить то, что не существует.
- И, наконец, я не очень рад такому огромному количеству
observeEvent
с несколькими future
шагами; было бы неплохо function
-измерить шаги или обобщить на произвольное количество шагов.