BASH перенаправляет `cat` в файл без новой строки

Попробуйте следующее:

Определение таблицы:

DROP TABLE IF EXISTS category;
CREATE TABLE category (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(20),
    parent_id INT,
    CONSTRAINT fk_category_parent FOREIGN KEY (parent_id)
    REFERENCES category (id)
) engine=innodb;

Экспериментальные строки:

INSERT INTO category VALUES
(19, 'category1', NULL),
(20, 'category2', 19),
(21, 'category3', 20),
(22, 'category4', 21),
(23, 'categoryA', 19),
(24, 'categoryB', 23),
(25, 'categoryC', 23),
(26, 'categoryD', 24);

Рекурсивная хранимая процедура:

DROP PROCEDURE IF EXISTS getpath;
DELIMITER $$
CREATE PROCEDURE getpath(IN cat_id INT, OUT path TEXT)
BEGIN
    DECLARE catname VARCHAR(20);
    DECLARE temppath TEXT;
    DECLARE tempparent INT;
    SET max_sp_recursion_depth = 255;
    SELECT name, parent_id FROM category WHERE id=cat_id INTO catname, tempparent;
    IF tempparent IS NULL
    THEN
        SET path = catname;
    ELSE
        CALL getpath(tempparent, temppath);
        SET path = CONCAT(temppath, '/', catname);
    END IF;
END$$
DELIMITER ;

Функция обертки для хранимой процедуры:

DROP FUNCTION IF EXISTS getpath;
DELIMITER $$
CREATE FUNCTION getpath(cat_id INT) RETURNS TEXT DETERMINISTIC
BEGIN
    DECLARE res TEXT;
    CALL getpath(cat_id, res);
    RETURN res;
END$$
DELIMITER ;

Выберите пример:

SELECT id, name, getpath(id) AS path FROM category;

Выход:

+----+-----------+-----------------------------------------+
| id | name      | path                                    |
+----+-----------+-----------------------------------------+
| 19 | category1 | category1                               |
| 20 | category2 | category1/category2                     |
| 21 | category3 | category1/category2/category3           |
| 22 | category4 | category1/category2/category3/category4 |
| 23 | categoryA | category1/categoryA                     |
| 24 | categoryB | category1/categoryA/categoryB           |
| 25 | categoryC | category1/categoryA/categoryC           |
| 26 | categoryD | category1/categoryA/categoryB/categoryD |
+----+-----------+-----------------------------------------+

Фильтрация строк определенным путем :

SELECT id, name, getpath(id) AS path FROM category HAVING path LIKE 'category1/category2%';

Выход:

+----+-----------+-----------------------------------------+
| id | name      | path                                    |
+----+-----------+-----------------------------------------+
| 20 | category2 | category1/category2                     |
| 21 | category3 | category1/category2/category3           |
| 22 | category4 | category1/category2/category3/category4 |
+----+-----------+-----------------------------------------+
0
задан JWAspin 13 July 2018 в 19:57
поделиться

3 ответа

С этими входами:

userInput="Test Test Test"

echo "Line 1
Line 2
Line 3" >file1

echo "Line 4
Line 5
Line 6" >file2

Я бы сделал:

printf "%s%s%s" "$(cat file1)" "$userInput" "$(cat file2)" >newfile

Создание >newfile эквивалентно touch и добавлению контента на вашем первом шаге , Чуть легче увидеть намерение с этим.

Я получаю:

$ cat newfile
Line 1
Line 2
Line 3Test Test TestLine 4
Line 5
Line 6
1
ответ дан dawg 17 August 2018 в 12:10
поделиться
  • 1
    Я предполагаю, что вы хотите 3 %s, а не $s в строке формата? Хотя printf '%s' "$(cat file1)" "$userInput" "$(cat file2)" будет иметь тот же эффект. – Charles Duffy 13 July 2018 в 20:42
  • 2
    @CharlesDuffy: Да, спасибо, но, как ни странно, это все равно работает! – dawg 13 July 2018 в 20:50
  • 3
    Когда переменная пуста, она будет работать одинаково %s%s или %s - повторять строку формата, когда она заканчивается. Когда s не пуст, тогда все будет интересно. :) – Charles Duffy 13 July 2018 в 20:50
  • 4
    Удивительно, это определенно лучшее решение, спасибо! – JWAspin 16 July 2018 в 14:31
touch newFile
echo -n "$(cat file1)" > newFile
echo -n $userInput >> newFile
cat file2 >> newFile

Это сделало трюк.

0
ответ дан Charles Duffy 17 August 2018 в 12:10
поделиться
  • 1
    Тройные обратные ссылки - дополнение GitHub к Markdown - они не являются частью синтаксиса базовой линии и не выполняются парсером StackOverflow. Используйте четырехмерные отступы, созданные кнопкой {}, для форматирования многострочного кода; это также позволяет выделить синтаксис, который не попадает в обратную сторону. – Charles Duffy 13 July 2018 в 20:40
  • 2
    ... говоря скорее с контентом, чем с формой, вы на самом деле удалили строку, которая существовала в файле здесь; это потому, что $(...) удаляет последнюю строку новой строки из вывода ... - поэтому ваш вывод имеет меньшее количество строк, чем входные файлы; вы не передаете контент без добавления новой строки, но активно удаляет новую строку, когда вы это делаете. – Charles Duffy 13 July 2018 в 20:41
  • 3
    (Кроме того, вы наверняка хотите "$userInput", а не $userInput, если вы не хотите, чтобы * был заменен на список имен файлов в каталоге, где выполняется ваш код, см. BashPitfalls # 14 ). – Charles Duffy 13 July 2018 в 20:49
  • 4
    @CharlesDuffy снова благодарит за все эти объяснения, я так сильно был на Slack, что я использовал тройные обратные ссылки из привычки. ... Теперь также становится более понятным, почему «$ (...)» фактически работал так, как он. Между VIM "скрыть" newline и $ (...), удалив эту новую строку, я был полностью смущен поведением, которое я видел. Спасибо, что объяснили, как это работает! (Теперь, время, чтобы действительно узнать printf, очевидно, это то, что я должен знать уже сейчас) – JWAspin 16 July 2018 в 14:44

Как и все другие инструменты Unix, Vim считает \n ограничителем строки , а не разделителем строки .

Это означает, что перевод строки после последний фрагмент текста будет считаться частью последней строки и не будет показывать дополнительную пустую строку.

Если нет вершинного перевода строки, Vim вместо этого отобразит [noeol] в строке состояния, когда файл загружен:

foo
~
~
~
~
~
"file" [noeol] 1L, 3C            1,1           All
        ^---- Here

Таким образом, нет, строка перевода определенно является частью вашего файла и не добавляется bash каким-либо образом.

Если вы хотите удалить все трейлинг-линии , вы можете сделать это как побочный эффект расширения команды:

printf '%s' "$(<file1)" >> newfile
2
ответ дан that other guy 17 August 2018 в 12:10
поделиться
  • 1
    Это многое объясняет, спасибо! Я не понял, что VIM «скрывался». такие новые строки, поэтому мой вопрос был основан на непонимании того, откуда эта новая линия. – JWAspin 16 July 2018 в 14:30
  • 2
    Я между этим ответом и тем, который я выбрал, но у другого есть более элегантное решение, но без этого ответа я все равно смутился бы по поводу всего VIM. SO должен добавить функцию для выбора нескольких ответов, объединенных в качестве решения :) – JWAspin 16 July 2018 в 14:47
Другие вопросы по тегам:

Похожие вопросы: